﻿#include "flexDlg.h"
#include "ui_flexDlg.h"
#include "QAlgoFactory.h"
#include <QPushButton>
#include "MyLabel.h"
#include <QFileDialog.h>
#include <QDesktopServices>
#include "Imgtfc.h"
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include "IPF.h"
#include <QStatusBar>
#include "Igv.h"
#include "flexDlgData.h"
#include <map>
#include "CParaContain.h"
#include "flexCommServer.h"
#include "mtp.h"
#include "flexGlobal.h"
#include "Icg.h"
#include "QSimulateCam.h"
#include "mss.h"
#include "IStateDlg.h"
#include "Icg.h"
#include "QILightCtrl.h"
#include "IVisionCtrlDlg.h"
#include "QCameraHK.h"
#include "QICamera.h"
#include "QCameraImp.h"
#include <functional>
#include "flexDispDlg.h"
#include "IMenuManager.h"
#include <fstream>
#include <sstream>
#include <QDateTime>
#include <QTime>
#include "ui_flexMesDlg.h"
#include "QWorkRateDlg.h"
#include"tcpMaster.h"


#pragma execution_character_set("utf-8")
using namespace std;

Q_DECLARE_METATYPE(StFixedData)

flexDlg::flexDlg(QWidget *parent)
	: MyAlgoDialog(parent)
	,pSimulateCam(IPF::gsSimulateCam())
{
	qRegisterMetaType<StFixedData>("StFixedData");
	//m_pflexdb = mksptr<flexdb>();
	LoadTranslateFile();
	ui = new Ui::flexDlg();
	ui->setupUi(this);
	m_pThis = this;
	m_AlgoName = "flex";
	gthpool = new ThreadPool();
	gthpool->CreateThread(10);
	gthpool->RegNotEnoughThreadEvent(OnNotEnoughThreadEventHandle_cb, this);
	InitVecData();
	InitFlexFilePath();
	ReadFlexIni();
	ui->radio_lockOffset->setChecked(m_bLockOffset);
	m_pMesData = new MesData(this);
	InitWindFromConstructor();
	connection();
	OnStart();
	connectLambda();
	std::string temp = Icg::getHalconDirPath().tostr() + "/flexRunning.hdev";
	m_hdev = new flexHalcon();
	m_hdev->InitHdevFullPath(temp.data());
	InitFlexPara();
	if (m_pflexComm == nullptr)
	{
		m_pflexComm = new flexCommServer();
	}
	if (m_pMaster == nullptr)
	{
		//m_pMaster = new PanelMaster();
	}
	g_pMesDlg = new flexMesDlg((QWidget*)IPF::GetMainWinPtr());
	g_pMesDlg->m_pMesData = m_pMesData;
	g_pMesDlg->m_pMesData->m_pflexMesDlg = g_pMesDlg;
	g_pMesDlg->m_pflexDlg = this;
	g_pMesDlg->OnBtnRefresh();
	g_pMesDlg->m_ipAddress = GetmtfInstance()->GetNetCardIp(g_pMesDlg->m_MacAddr);
	m_StartDateTime = QDateTime::currentDateTime();
	CheckCurrentTime();
	CleanUpRubbishDocuments();
	ReadWarningInfo();
	ui->Tab_Para->setCurrentIndex(1);
	m_pWorkRateDlg->DrawAllChart();
}

flexDlg::~flexDlg()
{
	delete m_hdev;
	m_pflexComm->m_bExit = true;
	mSleep(100);
	delete m_pflexComm;
	m_pflexComm = nullptr;
	delete 	g_pMesDlg;
	g_pMesDlg = nullptr;
	delete m_pMesData;
	m_pMesData = nullptr;
	delete ui;
}

void flexDlg::LoadTranslateFile()
{
	sptr qtTranslator = mksptr<QTranslator>();
	QString path = QApplication::applicationDirPath() + "/flex_language_en.qm";
	if (qtTranslator->load(path))
	{
		QApplication::installTranslator(qtTranslator.get());
	}
}

void flexDlg::Register()
{
	QAlgoFactory::GetInstance()->Register("flexDlg", CreatObj);
}

std::shared_ptr<MyDialog> flexDlg::CreatObj()
{
	return std::make_shared<flexDlg>((QWidget*)IPF::GetMainWinPtr());
}

void flexDlg::AutoInitParaFromFlow()
{
	m_pflow->m_NeedWriteDataAlgoDlgMap[m_AlgoName] = this;
	if (m_pflow->IsNewFlow()) return;
	InitParaFromDB();
}

void flexDlg::InitParaFromDB()
{
	ReadMemberVariablesFromDB();
	//InitTableFromDB();//Construct时已经更新
	//InitCameraPara();
	InitLight();
	DefaultPathConvert();
	ui->textBrowser_CmdPath->setText(m_PlcCmdPath);
	if (!m_PlcCmdPath.isEmpty()) ReadCmdPlc();
}

void flexDlg::ReadMemberVariablesFromDB()
{
   m_PlcCmdPath = GetmtfInstance()->QuerySingleValue2QString("conn1","成员变量表","string","变量名","m_PlcCmdPath",true);
}

void flexDlg::WriteMemberVariables2DB()
{
  GetmtfInstance()->UpdateSingleValue("conn1", "成员变量表", "string",m_PlcCmdPath, "变量名", "m_PlcCmdPath","1,1");
  MessageBoxTip("flex参数保存成功！");
}

void flexDlg::RegistGlobalCallBack()
{
	IPF::AddItemToolList(flexDlg::flexAddItemToToolLIst);//添加项目
	IPF::RegAutoCreateAlgoFun(flexDlg::flexAutoCreateAlgo);
	IPF::RegDispOrCreateDlgFun(flexDlg::flexDispOrCreateDlg);
	IPF::RegWriteDataFun(flexDlg::flexWriteDataFun);
	IPF::GetSetRobotCoorByComm() = GetRobotCoorByComm_cb;
	IPF::GetSetRelativeMoveFun() = RelativeMoveFun_cb;


	IPF::RegInitStatusBarFun(DispVersion_cb);
	if (m_pflexDispDlg==nullptr) m_pflexDispDlg = new flexDispDlg();
	IPF::RegCustomDlg(tr("信息"),m_pflexDispDlg);
	IPF::RegLogDispParaFun(flexDispDlg::logDisp, "mVisonAppender", m_pflexDispDlg);
	IPF::RegCameraLinkStateFun(CameraLinkState_cb);
	IMenuManager::RegShowDataInteractionDlgFun(OnDataInteraction_cb);
	IPF::GetSetReadImgInfoFun() = GetImgInfo_cb;
	IPF::GetSetRotateCenterOperateDBFun() = WriteRotateCenter2DB_cb;
	IPF::GetSetCaliperToolOpDBFun() = WriteStdPos2DB_cb;
	IPF::GetSetDispDlgTabWidgetFun() = DispWorkRateInfo_cb;
}

void flexDlg::flexAddItemToToolLIst(MyTreeWidget* pTreeWidget)
{
	//项目
	QTreeWidgetItem* root = pTreeWidget->AddTreeRoot("项目");
	pTreeWidget->AddTreeNode(root, "flex");
}

void flexDlg::flexAutoCreateAlgo(QString strSeletAlgo, std::string& AlgoName, std::shared_ptr<QFlowsBase>& pflow, void* pObj)
{
	if (strSeletAlgo != "flex") return;
	if (pObj != nullptr)
	{
		AutoCreateAlgoDlgByLoadFlow<flexDlg>(AlgoName, "flexDlg", pflow);
	}
}

void  flexDlg::flexDispOrCreateDlg(QString strSeletAlgo, void* pObj)
{
	if (strSeletAlgo != "flex") return;
	auto p = DispOrNewCreateAlgoDlg<flexDlg>(strSeletAlgo, "flexDlg");
}

void flexDlg::flexWriteDataFun(std::map<QString, MyAlgoDialog*>& WriteDataFunMap, CParaContain& para)
{
	if (WriteDataFunMap["flex"] != nullptr)
	{
		CDataBase* ptr = new flexDlgData();
		ptr->writeData(WriteDataFunMap["flex"]);
		para.m_VecDataPtr.push_back(ptr);
		m_pThis->WriteMemberVariables2DB();
	}
}

int flexDlg::GetRobotCoorByComm_cb(QPointF* pointValue, int* robotID, int* R_AxisNo, int* ImgProcID, int* PointIndex, double* R, double* Z)
{
	m_isGetRobotPos = false;
	if (m_pflexComm == nullptr) return -1;
	m_pflexComm->GetAbsPos(*robotID, *R_AxisNo);
	bool bCheckTimeOut = false;
	auto starttime = GetmtfInstance()->GetTimeNow();
	while (!m_isGetRobotPos)
	{
		QCoreApplication::processEvents();
		auto endtime = GetmtfInstance()->GetTimeNow();	
		if (GetmtfInstance()->durationTime(endtime,starttime,TimeType::second) > 5)
		{
			MessageBoxTip("获取机械手位置超时！");
			LOG_DEBUG(glogger, MultUtf82Mult2("获取机械手位置超时！"));
			bCheckTimeOut = true;
			break;
		}
	}
	if (bCheckTimeOut)
	{
		(*pointValue).rx() = 999999;
		(*pointValue).ry() = 999999;
		*R = 999999;
		return -2;
	}
	else
	{
		(*pointValue).rx() = m_GetRobotPos.x;
		(*pointValue).ry() = m_GetRobotPos.y;
		*R = m_GetRobotPos.R/1000;//下位机*1000发出来
	}
	m_isGetRobotPos = false;
	return 0;
}
           
void flexDlg::RelativeMoveFun_cb(int* robotID, int* R_AxisNo, double* x, double* y, double* Degree, int* z, int* pawStatus)
{
	if (m_pflexComm == nullptr) return ;
	m_pflexComm->RelativeMove(*robotID, *R_AxisNo,*x,*y,*Degree*1000);

}

void flexDlg::InitVecData()
{
	for (int i = 0; i < 4; i++)
	{
		m_GroupImg[i] = mksptr<HObject>();
	}
	for (int i=0;i<12;i++)
	{
		m_NnozzleImgRoi[i] = mksptr<HObject>();
		m_ResultRegion[i] = mksptr<HObject>();
		m_Cross[i] = mksptr<HObject>();
		m_ModelContourXld[i] = mksptr<HObject>();
		m_SearchContourXld[i] = mksptr<HObject>();
		m_PointCrossXld[i] = mksptr<HObject>();
	}
	m_SecondScanImg= mksptr<HObject>();


	DataInfo temp;
	OffsetLimit  temp2;

	m_RotateCenterImg.clear();
	m_StandOffsetLoadRobot.clear();
	m_StandImagePos.clear();
	m_LightIntensity.clear();
	m_OffsetLimit.clear();

	for (int i = 0; i <6; i++)
	{
		m_StandOffsetLoadRobot.push_back(temp);	
		m_NozzlePosRobot.push_back(temp);
		m_CameraPosRobot.push_back(temp);
	}
	for (int i = 0; i < 6; i++)
	{
		m_LightIntensity.push_back(temp);
	}
	for (int i = 0; i < 1; i++)//放料1个，共1个
	{
		m_RotateCenterImg.push_back(temp);	
	}
	for (int i = 0; i < 2; i++)
	{
		m_ManualBCRobot.push_back(temp);//2载盘标准图像位BC
		m_OffsetLimit.push_back(temp2);//2载盘防呆标准图像位置,
		m_StandImagePos.push_back(temp);//2载盘标准图像位置,
	}

	for (int i = 0; i < 3; i++)//取料1个，放料1个，防呆1个，共3个
	{
		m_CameraPara.push_back(temp); //相机参数：取料1个，放料1个，防呆1个，共3个
		m_ControlPara.push_back(temp);
	}
}

void flexDlg::InitFlexFilePath()
{
	Icg::getAppFilePath() = GetmtfInstance()->CreateInnerFolder(0, "DataFile/Panel/File");
	Icg::getHalconDirPath()= GetmtfInstance()->CreateInnerFolder(0, "DataFile/Panel/File/Hdev");
	Icg::getFlowDataDirPath() = GetmtfInstance()->CreateInnerFolder(0, "DataFile/Panel/File/FlowData");
	Icg::getModelFileDirPath() = GetmtfInstance()->CreateInnerFolder(0, "DataFile/Panel/File/Model");
	Icg::getJsonFileDirPath() = GetmtfInstance()->CreateInnerFolder(0, "DataFile/Panel/File/JsonFile");
	Icg::getCalibFileDirPath()= GetmtfInstance()->CreateInnerFolder(0, "DataFile/Panel/File/Calibrate");
	Icg::get2DCodeHandlePath() = GetmtfInstance()->CreateInnerFolder(0, "DataFile/Panel/File/2DCodeModel");
	Icg::getPlcCmdDirPath() = GetmtfInstance()->CreateInnerFolder(0, "DataFile/Panel/File/PlcCmd");
	Icg::getMetrologyHandleFileDirPath() = GetmtfInstance()->CreateInnerFolder(0, "DataFile/Panel/File/Metrology");

	m_FlexiniPath = GetmtfInstance()->CreateInnerFile(0, "Panel/ini", "Panel.ini");
	m_SaveSnMesCheckCsvFolderPath= GetmtfInstance()->CreateExteriorFolder("D:/Data/PanelData/SnMes");
	m_CheckSnFileFullPath = GetmtfInstance()->CreateInnerFile(0, "Panel", "CheckSn.text");
	ReadCheckSnCsvData(m_CheckSnFileFullPath,m_CheckSnMap);

	m_RectificationDataFolderPath = GetmtfInstance()->CreateExteriorFolder("D:/Data/PanelData/Rectification");
	m_FlexPictureFolderPath= GetmtfInstance()->CreateExteriorFolder("D:/Data/PanelData/Picture");
	m_RepeatTestDataFolderPath = GetmtfInstance()->CreateExteriorFolder("D:/Data/PanelData/RepeatTest");
	m_PlcLogDataFolderPath= GetmtfInstance()->CreateExteriorFolder("D:/Data/PanelData/Alert");
	m_WorkRateFolderPath = GetmtfInstance()->CreateExteriorFolder("D:/Data/PanelData/WorkRate");


	for (auto iter= m_CheckSnMap.begin();iter!= m_CheckSnMap.end();iter++)
	{
		LOG_DEBUG(glogger, MultUtf82Mult2("点检SN:")<< MultUtf82Mult(iter->first)<< MultUtf82Mult2(" SN长度:")<< iter->first.length());
	}
}

void flexDlg::ReadFlexIni()
{
	QString temp = GetmtfInstance()->ReadInIFileStr("setting", "m_bShieldAppearance", m_FlexiniPath);
  if (temp=="true")
  {
	  m_bShieldAppearance = true;
  } 
  else
  {
	  m_bShieldAppearance = false;
  }
  ui->radio_ShieldAppearance->setChecked(m_bShieldAppearance);

  temp = GetmtfInstance()->ReadInIFileStr("setting", "m_bShieldTrayLocation", m_FlexiniPath);
  if (temp == "true")
  {
	  m_bShieldTrayLocation = true;
  }
  else
  {
	  m_bShieldTrayLocation = false;
  }
  ui->radio_shieldTrayLocation->setChecked(m_bShieldTrayLocation);
   temp = GetmtfInstance()->ReadInIFileStr("setting", "m_Days", m_FlexiniPath);
   m_Days = temp.toInt();

  temp = GetmtfInstance()->ReadInIFileStr("setting", "m_bCheckTime", m_FlexiniPath);
  if (temp == "true")m_bCheckTime = true;
  else m_bCheckTime = false;

  m_CheckTime[0]= GetmtfInstance()->ReadInIFileStr("setting", "CheckTime_0", m_FlexiniPath);
  m_CheckTime[1] = GetmtfInstance()->ReadInIFileStr("setting", "CheckTime_1", m_FlexiniPath);

  ui->radio_SaveOkPic->setChecked(m_bSaveOkPic);
  ui->radio_SaveNGPic->setChecked(m_bSaveNGPic);

  temp = GetmtfInstance()->ReadInIFileStr("setting", "m_bAlwaysBright", m_FlexiniPath);
  if (temp == "true") m_bAlwaysBright = true, ui->radio_AlwaysBright->setChecked(m_bAlwaysBright);
  else m_bAlwaysBright = false;


  temp = GetmtfInstance()->ReadInIFileStr("setting", "Light_1_Channel", m_FlexiniPath);
  m_vecLightChannel.push_back(temp.toInt());
  temp = GetmtfInstance()->ReadInIFileStr("setting", "Light_2_Channel", m_FlexiniPath);
  m_vecLightChannel.push_back(temp.toInt());
  temp = GetmtfInstance()->ReadInIFileStr("setting", "Light_3_Channel", m_FlexiniPath);
  m_vecLightChannel.push_back(temp.toInt());
  temp = GetmtfInstance()->ReadInIFileStr("setting", "Light_4_Channel", m_FlexiniPath);
  m_vecLightChannel.push_back(temp.toInt());

  temp = GetmtfInstance()->ReadInIFileStr("count", "output", m_FlexiniPath);
  m_pflexDispDlg->m_output = temp.toInt();
  m_pflexDispDlg->m_pflexDlg = this;
  m_pflexDispDlg->ShowCountInfo(m_pflexDispDlg->m_output, m_pflexDispDlg->m_uphCount);

}

void flexDlg::showEvent(QShowEvent* event)
{


}

void flexDlg::CheckCurrentTime()
{
	auto fun = [=] {
		int day,hour, minute, second;//倒计时时长
		int curday, curhour, curminute, cursecond;//当前时间点

		bool bReset = false;
		bool bFinishLastWrite = false;
		bool bFirst = true;
		QString ConnName = QTime::currentTime().toString("hhmmsszzz");
		m_pflexdb->CreateflexDataConnection(ConnName);


		while (m_bCheckTime)
		{
			QDateTime curDateTime = QDateTime::currentDateTime();
			QDate curDate = curDateTime.date();
			QTime curTime = curDateTime.time();
			curhour = curTime.hour();
			curminute = curTime.minute();
			cursecond = curTime.second();

			bool res = GetmtfInstance()->CheckCurrentTimeRange(m_CheckTime[0], m_CheckTime[1]);
			if (res)//白班
			{
				m_isDayShift = true;
				GetmtfInstance()->CurrentTimeToFutureTime(m_CheckTime[1], day, hour, minute, second);
				QString text = QString("当前白班，距离白班结束还剩：%1 天 %2 时 %3 分 %4 秒 ").arg(day).arg(hour).arg(minute).arg(second);
				LOG_DEBUG(glogger, MultUtf82Mult(text));
				if (((hour == 11) && (minute == 59) && ((50 <= second)) && (second <= 59)) || bFirst)
				{
					if (bFirst)
					{
						bFirst = false;
						if (GetmtfInstance()->CheckCurrentTimeRange("00:00:00", m_CheckTime[0]))
						{
							curDate = curDate.addDays(-1);
						}
						m_pflexdb->GetSetWorkRateCurTableName() = "DayWorkRate_" + curDate.toString("yyyy_MM_dd");
						m_pflexdb->GetSetLogCurTableName() = "DayLog_" + curDate.toString("yyyy_MM_dd");
						GetSetTableName() = curDate.toString("yyyy_MM_dd") + "_Day";
						WriteWorkRateCsvData(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, m_pflexDispDlg->m_output, 0, 0, 0, 0, 0);
						m_pflexdb->WriteWorkRateDB(ConnName,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, m_pflexDispDlg->m_output, 0, 0, 0, 0, 0);
						emit m_pWorkRateDlg->postInitCbxShift();
						LOG_DEBUG(glogger, MultUtf82Mult2("白班启动时写入"));
					}
					else {
						m_pflexdb->GetSetWorkRateCurTableName() = "DayWorkRate_" + curDate.toString("yyyy_MM_dd");
						m_pflexdb->GetSetLogCurTableName() = "DayLog_" + curDate.toString("yyyy_MM_dd");
						GetSetTableName() = curDate.toString("yyyy_MM_dd") + "_Day";
						LOG_DEBUG(glogger, MultUtf82Mult2("换成白班表头"));
					}
				}
				else if (((hour == 12) && (minute == 0) && ((0 <= second)) && (second <= 5)))
				{
					m_pflexdb->GetSetWorkRateCurTableName() = "DayWorkRate_" + curDate.toString("yyyy_MM_dd");
					m_pflexdb->GetSetLogCurTableName() = "DayLog_" + curDate.toString("yyyy_MM_dd");
					GetSetTableName() = curDate.toString("yyyy_MM_dd") + "_Day";
					LOG_DEBUG(glogger, MultUtf82Mult2("换成白班表头2"));
				}
			}
			else //晚班
			{
				m_isDayShift = false;
				GetmtfInstance()->CurrentTimeToFutureTime(m_CheckTime[0], day, hour, minute, second);
				QString text = QString("当前晚班，距离晚班结束还剩：%1 天 %2 时 %3 分 %4 秒 ").arg(day).arg(hour).arg(minute).arg(second);
				LOG_DEBUG(glogger, MultUtf82Mult(text));
																
				if (((hour == 11) && (minute == 59) && ((50 <= second)) && (second <= 59))  || bFirst)
				{
					if (bFirst)
					{
						bFirst = false;
						if (GetmtfInstance()->CheckCurrentTimeRange("00:00:00", m_CheckTime[0]))
						{
							curDate = curDate.addDays(-1);
						}
						m_pflexdb->GetSetWorkRateCurTableName() = "NightWorkRate_" + curDate.toString("yyyy_MM_dd");
						m_pflexdb->GetSetLogCurTableName() = "NightLog_" + curDate.toString("yyyy_MM_dd");
						GetSetTableName() = curDate.toString("yyyy_MM_dd") + "_Night";

						WriteWorkRateCsvData(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, m_pflexDispDlg->m_output, 0, 0, 0, 0, 0);
						m_pflexdb->WriteWorkRateDB(ConnName,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, m_pflexDispDlg->m_output, 0, 0, 0, 0, 0);
						emit m_pWorkRateDlg->postInitCbxShift();
						LOG_DEBUG(glogger, MultUtf82Mult2("晚班启动时写入"));
					}
					else {
						m_pflexdb->GetSetWorkRateCurTableName() = "NightWorkRate_" + curDate.toString("yyyy_MM_dd");
						m_pflexdb->GetSetLogCurTableName() = "NightLog_" + curDate.toString("yyyy_MM_dd");
						GetSetTableName() = curDate.toString("yyyy_MM_dd") + "_Night";
						LOG_DEBUG(glogger, MultUtf82Mult2("换成晚班表头"));
					}
				}
				else if (((hour == 12) && (minute == 0) && ((0 <= second)) && (second <= 5)))
				{
					m_pflexdb->GetSetWorkRateCurTableName() = "NightWorkRate_" + curDate.toString("yyyy_MM_dd");
					m_pflexdb->GetSetLogCurTableName() = "NightLog_" + curDate.toString("yyyy_MM_dd");
					GetSetTableName() = curDate.toString("yyyy_MM_dd") + "_Night";
					LOG_DEBUG(glogger, MultUtf82Mult2("换成晚班表头2"));
				}
			}

			if (((hour == 11) && (minute == 59) && ((50 <= second)) && (second <= 59)) || bFinishLastWrite)//每班起点，第一次				
			{
				bFinishLastWrite = false;

				if (bReset) { goto label_1; }
				bReset = true;
				//总数据===============================================================================
				m_pflexDispDlg->m_TotalWorkTime = 0;
				m_pflexDispDlg->m_TotalWaitTime = 0;
				m_pflexDispDlg->m_TotalWarningTime = 0;
				m_pflexDispDlg->m_CountTimes = 0;
				m_iTotalPositingFail = 0;

				TotalWorkTime = m_pflexDispDlg->m_TotalWorkTime;
				TotalWaitTime = m_pflexDispDlg->m_TotalWaitTime;
				TotalWarningTime = m_pflexDispDlg->m_TotalWarningTime;
				TotalPositingFail = m_iTotalPositingFail;

				m_pflexDispDlg->m_startTime = std::chrono::steady_clock::now();

				m_pflexDispDlg->m_TotalTime = 0;
				TotalTime = m_pflexDispDlg->m_TotalTime;

				TotalFaultTime = 0;
				TotalWorkRate = 0;
				TotalWaitRate = 0;
				TotalFaultRate = 0;

				m_pflexDispDlg->m_output = 0;
				TotalOutPut = m_pflexDispDlg->m_output;
				GetmtfInstance()->WriteInIFileStr("count", "output", QString::number(TotalOutPut), m_FlexiniPath);

				//每小时数据===============================================================================
				lastTotalWorkTime = 0;
				lastTotalWaitTime = 0;
				lastTotalWarningTime = 0;

				curWorkTime = 0;
				curWaitTime = 0;
				curWarningTime = 0;
				curFaultTime = 0;
				workRate = 0;
				waitRate = 0;
				faultRate = 0;

				lastTotalOutput = 0;
				curOutPut = 0;

				lastPositingFail = 0;

				//===============================================================================
				lastTotalWorkTime = TotalWorkTime;
				lastTotalWaitTime = TotalWaitTime;
				lastTotalWarningTime = TotalWarningTime;
				lastTotalOutput = TotalOutPut;
				lastPositingFail = TotalPositingFail;
				//===============================================================================

				WriteWorkRateCsvData(TotalTime,
					curWorkTime, curWaitTime, curWarningTime, curFaultTime, curOutPut,
					workRate, waitRate, faultRate,
					TotalWorkTime, TotalWaitTime, TotalWarningTime, TotalFaultTime, TotalOutPut,
					TotalWorkRate, TotalWaitRate, TotalFaultRate, curPositingFail, TotalPositingFail);
				m_pflexdb->WriteWorkRateDB(ConnName,TotalTime,
					curWorkTime, curWaitTime, curWarningTime, curFaultTime, curOutPut,
					workRate, waitRate, faultRate,
					TotalWorkTime, TotalWaitTime, TotalWarningTime, TotalFaultTime, TotalOutPut,
					TotalWorkRate, TotalWaitRate, TotalFaultRate, curPositingFail, TotalPositingFail);
				emit m_pWorkRateDlg->postInitCbxShift(true);
				LOG_DEBUG(glogger, MultUtf82Mult2("当班第一次WorkRate写入完成！"));
			}

		label_1:	
			//if ((hour >= 1) && (minute >= 58))
			if (hour >=1)
			//if (hour >1)
			{
				bReset = false;
				if (curminute == 0 && cursecond <= 10)//每个整点
				{
					if ((curhour != QTime::fromString(m_CheckTime[0]).hour()) && (curhour != QTime::fromString(m_CheckTime[1]).hour()))
						ProcessCheckCurrentTimeData(ConnName);
					LOG_DEBUG(glogger, MultUtf82Mult2("整点WorkRate写入完成！"));
					std::this_thread::sleep_for(std::chrono::milliseconds(1000 * 3588));
					continue;
				}
			}
			//else if ((hour <1)||((hour == 1) && (minute < 58)))
			else if (hour <1)
			//else if (hour <= 1)
			{			
				if (((curminute == 0 && cursecond <= 2)) || (hour == 0 && minute == 0 && second <= 2))//每个整点及倒计时最后一次写入
				{
					if ((QTime::fromString(m_CheckTime[0]).minute()==0)&& (QTime::fromString(m_CheckTime[1]).minute() == 0))
					{
						if ((curhour != QTime::fromString(m_CheckTime[0]).hour()) && (curhour != QTime::fromString(m_CheckTime[1]).hour()))
						{
							ProcessCheckCurrentTimeData(ConnName);
							LOG_DEBUG(glogger, MultUtf82Mult2("倒计时1小时内整点WorkRate写入！"));
						}
					}
					else {
						ProcessCheckCurrentTimeData(ConnName);
						LOG_DEBUG(glogger, MultUtf82Mult2("倒计时1小时内整点WorkRate写入！"));
					}


					if (hour == 0 && minute == 0 && second <= 3) {
						bFinishLastWrite = true;
						LOG_DEBUG(glogger, MultUtf82Mult2("当班最后一次写入完成"));
						mSleep(5000); continue; }
				}
			}
			mSleep(2000);
		}
		m_pflexdb->removeConnection(ConnName);
	};
	gthpool->AddTask(fun);
}

void flexDlg::ProcessCheckCurrentTimeData(QString ConnName)
{
	//总数据===============================================================================
	TotalWorkTime = m_pflexDispDlg->m_TotalWorkTime;
	TotalWaitTime = m_pflexDispDlg->m_TotalWaitTime;
	TotalWarningTime = m_pflexDispDlg->m_TotalWarningTime;
	TotalPositingFail = m_iTotalPositingFail;

	auto TimeNow = std::chrono::steady_clock::now();
	m_pflexDispDlg->m_TotalTime = GetmtfInstance()->durationTime(TimeNow, m_pflexDispDlg->m_startTime, TimeType::second);

	TotalTime = m_pflexDispDlg->m_TotalTime;
	if (TotalWorkTime > TotalTime) TotalWorkTime = TotalTime;
	if (TotalWaitTime > TotalTime) TotalWaitTime = TotalTime;
	if (TotalWarningTime > TotalTime) TotalWarningTime = TotalTime;
	TotalFaultTime = TotalTime - TotalWorkTime - TotalWaitTime - TotalWarningTime;
	TotalWorkRate = TotalWorkTime / TotalTime;
	TotalWaitRate = TotalWaitTime / TotalTime;
	TotalFaultRate = 1 - TotalWorkRate - TotalWaitRate;

	TotalOutPut = m_pflexDispDlg->m_output;

	//每小时数据===============================================================================
	curWorkTime = TotalWorkTime - lastTotalWorkTime;
	curWaitTime = TotalWaitTime - lastTotalWaitTime;
	curWarningTime = TotalWarningTime - lastTotalWarningTime;
	curFaultTime = 3600 - curWorkTime - curWaitTime - curWarningTime;
	if (curFaultTime < 0) curFaultTime = 0;
	workRate = curWorkTime / 3600.0;
	waitRate = curWaitTime / 3600.0;
	faultRate = 1 - workRate - waitRate;
	if (faultRate < 0) faultRate = 0;
	curOutPut = TotalOutPut - lastTotalOutput;
	curPositingFail = TotalPositingFail - lastPositingFail;
	//===============================================================================
	lastTotalWorkTime = TotalWorkTime;
	lastTotalWaitTime = TotalWaitTime;
	lastTotalWarningTime = TotalWarningTime;
	lastTotalOutput = TotalOutPut;
	lastPositingFail = TotalPositingFail;
	//===============================================================================

	WriteWorkRateCsvData(TotalTime,
		curWorkTime, curWaitTime, curWarningTime, curFaultTime, curOutPut,
		workRate, waitRate, faultRate,
		TotalWorkTime, TotalWaitTime, TotalWarningTime, TotalFaultTime, TotalOutPut,
		TotalWorkRate, TotalWaitRate, TotalFaultRate, curPositingFail, TotalPositingFail);
	m_pflexdb->WriteWorkRateDB(ConnName,TotalTime,
		curWorkTime, curWaitTime, curWarningTime, curFaultTime, curOutPut,
		workRate, waitRate, faultRate,
		TotalWorkTime, TotalWaitTime, TotalWarningTime, TotalFaultTime, TotalOutPut,
		TotalWorkRate, TotalWaitRate, TotalFaultRate, curPositingFail, TotalPositingFail);

	emit m_pWorkRateDlg->postInitCbxShift();
}

QString& flexDlg::GetSetTableName()
{
	lockup(m_TableNameMutex);
	return m_TableName;
}

void flexDlg::connection()
{
	connect(ui->btn_send_plc, &QPushButton::clicked, this, &flexDlg::OnPushButton);
	connect(ui->btn_FreshCmd_plc, &QPushButton::clicked, this, &flexDlg::OnPushButton);
	connect(ui->btn_load_cmd, &QPushButton::clicked, this, &flexDlg::OnPushButton);
	connect(ui->btn_openfolder_cmd, &QPushButton::clicked, this, &flexDlg::OnPushButton);
	connect(this, &flexDlg::postShowData, m_pflexDispDlg, &flexDispDlg::OnShowData);
	connect(ui->btn_func_test, &QPushButton::clicked, this, &flexDlg::OnFuncTest);
	//ui->btn_func_test->hide();
}

void flexDlg::connectLambda()
{
	connect(ui->radio_simulate, &QRadioButton::clicked, this, [&] {
		m_bSimulate = ui->radio_simulate->isChecked();
		});

	connect(ui->radio_simulateSavePic, &QRadioButton::clicked, this, [&] {
		m_bSimulateSavePic = ui->radio_simulateSavePic->isChecked();
		});

	connect(ui->radio_emptyRunning, &QRadioButton::clicked, this, [&] {
		ui->radio_emptyRunWithSimImg->setChecked(false);
		m_bEmpyRun = ui->radio_emptyRunning->isChecked();
		m_bEmpyRunWithSimImg = false;
		ui->radio_ShieldError->setChecked(false);
		m_bShieldError = false;
		});

	connect(ui->radio_emptyRunWithSimImg, &QRadioButton::clicked, this, [&] {
		ui->radio_emptyRunning->setChecked(false);
		m_bEmpyRunWithSimImg = ui->radio_emptyRunWithSimImg->isChecked();
		m_bEmpyRun = m_bEmpyRunWithSimImg;
		ui->radio_ShieldError->setChecked(false);
		m_bShieldError = false;
		});

	connect(ui->radio_ShieldError, &QRadioButton::clicked, this, [&] {
		m_bShieldError = ui->radio_ShieldError->isChecked();
		});

	connect(ui->checkBox_timeOut, &QCheckBox::clicked, this, [=]()
		{
			m_pflexComm->m_bCheckTimeOut = ui->checkBox_timeOut->isChecked();
		});

	connect(ui->checkBox_heartBeat, &QCheckBox::clicked, this, [=]()
		{
			m_pflexComm->m_bCheckHeartBeat = ui->checkBox_heartBeat->isChecked();
		});
	connect(ui->radio_SaveOkPic, &QCheckBox::clicked, this, [=]()
		{
			m_bSaveOkPic = ui->radio_SaveOkPic->isChecked();
		});
	connect(ui->radio_SaveNGPic, &QCheckBox::clicked, this, [=]()
		{
			m_bSaveNGPic = ui->radio_SaveNGPic->isChecked();
		});
	connect(ui->radio_ShieldCode, &QCheckBox::clicked, this, [=]()
		{
			m_bShield2DCode = ui->radio_ShieldCode->isChecked();
		});
	connect(ui->radio_ShieldAppearance, &QCheckBox::clicked, this, [=]()
		{
			m_bShieldAppearance = ui->radio_ShieldAppearance->isChecked();
		});
	ui->radio_ShieldAppearance->hide();
	connect(ui->radio_shieldTrayLocation, &QCheckBox::clicked, this, [=]()
		{
			m_bShieldTrayLocation = ui->radio_shieldTrayLocation->isChecked();
		});
	ui->radio_shieldTrayLocation->hide();

	connect(ui->radio_lockOffset, &QCheckBox::clicked, this, [=]()
		{
			m_bLockOffset = ui->radio_lockOffset->isChecked();
			UpdataTable_StandOffsetLoadRobot();
		});

	connect(ui->radio_Repeat_Test, &QCheckBox::clicked, this, [=]()
		{
			m_RepeatTest = ui->radio_Repeat_Test->isChecked();
		});
	connect(ui->radio_SaveOriginalPicture, &QCheckBox::clicked, this, [=]()
		{
			m_bSaveOriginalPicture = ui->radio_SaveOriginalPicture->isChecked();
		});
	connect(ui->radio_AlwaysBright, &QCheckBox::clicked, this, [=]()
		{
			m_bAlwaysBright = ui->radio_AlwaysBright->isChecked();			
			if (m_bAlwaysBright) 	GetmtfInstance()->WriteInIFileStr("setting", "m_bAlwaysBright", "true",m_FlexiniPath);
			else GetmtfInstance()->WriteInIFileStr("setting", "m_bAlwaysBright", "false",m_FlexiniPath);
			InitLight();
		});
	connect(ui->radio_OldEquipment, &QCheckBox::clicked, this, [=]()
		{
			m_bOldEquipment= ui->radio_OldEquipment->isChecked();
			if (m_bOldEquipment)
			{
				m_pMesData->m_bConnectMes = false;
				g_pMesDlg->ui->checkBox_connectMes->setChecked(m_pMesData->m_bConnectMes);
			}
		});
}


sptr<HObject> m_test;
bool  bfirst = true;
void flexDlg::OnFuncTest()
{
	//emit m_pWorkRateDlg->postInitCbxShift(true);
	//m_pflexdb->CleanUpOutdatedTables();
	if (bfirst) {
		bfirst = false;
		Icg::getNameCameraMap()[CAM_NAME_0]->GetSingleImage(m_test);
		DlgDispImg(m_pwnd[3], "", m_test);
	}
	else
	{
		//Icg::getNameCameraMap()[CAM_NAME_0]->GetSingleImage(m_test);
		DlgDispImg(m_pwnd[4], "", m_test);
	}
}

void flexDlg::OnStart()
{
	if (m_pflexComm == nullptr)
	{
		m_pflexComm = new flexCommServer;
	}
	connect(m_pflexComm, &flexCommServer::PostRecvRegist, m_pThis, &flexDlg::OnRecvRegist);
	//connect(m_pflexComm, &flexCommServer::PostRecvTakeDut, m_pThis, &flexDlg::OnRecvTakeDut);
	//connect(m_pflexComm, &flexCommServer::PostRecvPutDut, m_pThis, &flexDlg::OnRecvPutDut);
	connect(m_pflexComm, &flexCommServer::PostRecvWarning, m_pThis, &flexDlg::OnRecvRecvWarning);
	connect(m_pflexComm, &flexCommServer::PostRecvPhotograph, m_pThis, &flexDlg::OnRecvPhotograph);
	//connect(m_pflexComm, &flexCommServer::PostRecv_2DCode, m_pThis, &flexDlg::OnRecv_2DCode);
	connect(m_pflexComm, &flexCommServer::PostRecvTestResult, m_pThis, &flexDlg::OnRecvTestResult);
	connect(m_pflexComm, &flexCommServer::PostReEquipmentState, m_pThis, &flexDlg::OnRecvEquipmentState);

	connect(m_pflexComm, &flexCommServer::PostRecvReHeartBeat, m_pThis, &flexDlg::OnRecvReHeartBeat);
	connect(m_pflexComm, &flexCommServer::PostRecvReGetPos, m_pThis, &flexDlg::OnRecvReGetAbsPos);
	connect(m_pflexComm, &flexCommServer::PostRecvReAbsMove, m_pThis, &flexDlg::OnRecvReRelativeMove);

	connect(m_pflexComm, &flexCommServer::PostRecvReTakeDutResult, m_pThis, &flexDlg::OnRecvReTakeDutResult);
	connect(m_pflexComm, &flexCommServer::PostRecvRePutDutResult, m_pThis, &flexDlg::OnRecvRePutDutResult);
	connect(m_pflexComm, &flexCommServer::PostRecvReDefenceResult, m_pThis, &flexDlg::OnRecvReDefenceResult);

}

//表格========================================================================
void flexDlg::ReadCmdPlc()
{
	QStringList strSplit;
	m_vecPlcCmdSet.clear();
	GetmtfInstance()->ReadPlcCmdSetFile(m_PlcCmdPath, m_vecPlcCmdSet);
	ui->cbx_cmd_plc->clear();
	for (int i = 0; i < m_vecPlcCmdSet.size(); ++i)
	{
		ui->cbx_cmd_plc->insertItem(i, QString::number(m_vecPlcCmdSet.at(i).at(0).toInt()));
	}
}

void flexDlg::InitWindFromConstructor()
{
	int TableNum = 0;
	m_pTable[TableNum] = ui->table_StandOffset;
	m_pTable[TableNum]->SetTableHeader("吸嘴号", "吸头X", "吸头Y", "吸头R", "相机X", "相机Y", "相机R", "offsetX", "offsetY","备注");
	m_pTable[TableNum]->SetTableRowCount(m_StandOffsetLoadRobot.size());
	m_pTable[TableNum]->InitOrderAtColumn(0);
	m_pTable[TableNum]->m_TableName = "StandOffsetRobot";
	//m_pTable[TableNum]->setFocusPolicy(Qt::ClickFocus);
	connect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
	connect(m_pTable[TableNum], &MyTableWidget::cellDoubleClicked, this, &flexDlg::OnCellDoubleClicked);
	UpdataTable_StandOffsetLoadRobot();

	TableNum++;//1
	m_pTable[TableNum] = ui->table_StdImgPos;
	m_pTable[TableNum]->SetTableHeader("放料顺序", "图像坐标X", "图像坐标Y", "角度R", "备注");
	m_pTable[TableNum]->SetTableRowCount(m_StandImagePos.size());
	m_pTable[TableNum]->InitOrderAtColumn(0);
	m_pTable[TableNum]->SetTableCellSize(40, 40, 30, 80);
	m_pTable[TableNum]->horizontalHeader()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
	m_pTable[TableNum]->m_TableName = "StandPosImg";
	connect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
	connect(m_pTable[TableNum], &MyTableWidget::cellDoubleClicked, this, &flexDlg::OnCellDoubleClicked);
	UpdataTable_StandImgPos();

	              
	TableNum++;//2
	m_pTable[TableNum] = ui->table_RotateCenter;
	m_pTable[TableNum]->SetTableHeader("吸嘴号", "图像坐标X", "图像坐标Y", "备注");
	m_pTable[TableNum]->SetTableRowCount(m_RotateCenterImg.size());
	m_pTable[TableNum]->InitOrderAtColumn(0);
	m_pTable[TableNum]->m_TableName = "RotateCenterImg";
	connect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
	connect(m_pTable[TableNum], &MyTableWidget::cellDoubleClicked, this, &flexDlg::OnCellDoubleClicked);
	UpdataTable_RotateCenter();

	TableNum++;//3
	m_pTable[TableNum] = ui->table_Manual;
	m_pTable[TableNum]->SetTableHeader("放料顺序", "X补偿", "Y补偿", "R补偿", "备注");
	m_pTable[TableNum]->SetTableRowCount(m_ManualBCRobot.size());
	m_pTable[TableNum]->InitOrderAtColumn(0);
	//m_pTable[TableNum]->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
	//m_pTable[TableNum]->SetTableCellSize(40, 50, 120, 120, 100);

	m_pTable[TableNum]->SetTableCellSize(40, 50, 120, 120, 100);
	m_pTable[TableNum]->horizontalHeader()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
	m_pTable[TableNum]->m_TableName = "ManualBCrobot";
	connect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
	connect(m_pTable[TableNum], &MyTableWidget::cellDoubleClicked, this, &flexDlg::OnCellDoubleClicked);
	UpdataTable_ManualBC();

	TableNum++;//4
	m_pTable[TableNum] = ui->table_light;
	m_pTable[TableNum]->SetTableHeader("位置ID", "亮度", "备注");
	m_pTable[TableNum]->SetTableRowCount(m_LightIntensity.size());
	m_pTable[TableNum]->InitOrderAtColumn(0);
	m_pTable[TableNum]->m_TableName = "light";
	connect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
	connect(m_pTable[TableNum], &MyTableWidget::cellDoubleClicked, this, &flexDlg::OnCellDoubleClicked);
	UpdataTable_light();

	TableNum++;//5
	m_pTable[TableNum] = ui->table_LimitData;
	m_pTable[TableNum]->SetTableHeader("载具穴位号", "StdX", "StdY", "StdR", "X-", "X+", "Y-", "Y+", "R-", "R+", "备注");
	m_pTable[TableNum]->SetTableRowCount(m_OffsetLimit.size());
	m_pTable[TableNum]->InitOrderAtColumn(0);
	//m_pTable[TableNum]->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
	//m_pTable[TableNum]->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
	m_pTable[TableNum]->horizontalHeader()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
	m_pTable[TableNum]->SetTableCellSize(40, 60, 60,80, 80, 60, 60, 60, 60, 60, 60, 80);
	m_pTable[TableNum]->m_TableName = "LocationLimit";
	connect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
	connect(m_pTable[TableNum], &MyTableWidget::cellDoubleClicked, this, &flexDlg::OnCellDoubleClicked);
	UpdataTable_LocationLimtPara();

	TableNum++;//6
	m_pTable[TableNum] = ui->table_ControlPara;
	m_pTable[TableNum]->SetTableHeader("位置ID", "值", "备注");
	m_pTable[TableNum]->SetTableRowCount(m_ControlPara.size());
	m_pTable[TableNum]->InitOrderAtColumn(0);
	m_pTable[TableNum]->m_TableName = "ControlPara";
	connect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
	connect(m_pTable[TableNum], &MyTableWidget::cellDoubleClicked, this, &flexDlg::OnCellDoubleClicked);
	UpdataTable_ControlPara();

	TableNum++;//7
	m_pTable[TableNum] = ui->table_camera;
	m_pTable[TableNum]->SetTableHeader("相机ID", "曝光", "增益", "伽马", "备注");
	m_pTable[TableNum]->SetTableRowCount(m_CameraPara.size());
	m_pTable[TableNum]->InitOrderAtColumn(0);
	m_pTable[TableNum]->horizontalHeader()->setSectionResizeMode(3, QHeaderView::ResizeToContents);
	m_pTable[TableNum]->SetTableCellSize(40, 60, 60, 80, 80, 60);
	m_pTable[TableNum]->m_TableName = "CameraPara";
	connect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
	connect(m_pTable[TableNum], &MyTableWidget::cellDoubleClicked, this, &flexDlg::OnCellDoubleClicked);
	UpdataTable_CameraPara();

	ui->checkBox_timeOut->setChecked(Icg::getbCheckTimeOut());
	ui->checkBox_heartBeat->setChecked(Icg::getbCheckHeartBeat());

	ui->radio_SaveOkPic->setChecked(m_bSaveOkPic);
	ui->radio_SaveNGPic->setChecked(m_bSaveNGPic);

}

void flexDlg::InitTableFromDB()
{
	UpdataTable_StandOffsetLoadRobot();
	UpdataTable_StandImgPos();
	UpdataTable_RotateCenter();
	UpdataTable_ManualBC();
	UpdataTable_light();
	UpdataTable_LocationLimtPara();
	UpdataTable_ControlPara();
	UpdataTable_CameraPara();
}

void flexDlg::OnCellDoubleClicked(int row, int column)
{
	MyTableWidget* pTable = (MyTableWidget*)sender();
    m_ClickedValue = pTable->GetText(row, column);
}

void flexDlg::OnEditTable(int row, int column)
{
	MyTableWidget* pTable = (MyTableWidget*)sender();
	auto res = QMessageBox::StandardButton::NoButton;
	res = QMessageBox::information(0, "提示", "是否更改此参数?", QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::No);
	if (res == QMessageBox::StandardButton::No)
	{
		disconnect(pTable, &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
		pTable->setItemEx(column, row, m_ClickedValue);
		connect(pTable, &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
		return;
	}
	QString value;
	value = pTable->GetText(row, column);
	if (pTable->m_TableName == "StandOffsetRobot")
	{
		if (column == 1)
		{
			m_NozzlePosRobot.at(row).x = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "取料位标定参数", "吸头X", value, "rowid", QString::number(row + 1));
		}
		else if (column == 2)
		{
			m_NozzlePosRobot.at(row).y = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "取料位标定参数", "吸头Y", value, "rowid", QString::number(row + 1));
		}
		else if (column == 3) {
			m_NozzlePosRobot.at(row).R = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "取料位标定参数", "吸头R", value, "rowid", QString::number(row + 1));
		}

		else if (column == 4)
		{
			m_CameraPosRobot.at(row).x = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "取料位标定参数", "相机X", value, "rowid", QString::number(row + 1));
		}
		else if (column == 5) {
			m_CameraPosRobot.at(row).y = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "取料位标定参数", "相机Y", value, "rowid", QString::number(row + 1));
		}
		else if (column == 6) {
			m_CameraPosRobot.at(row).R = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "取料位标定参数", "相机R", value, "rowid", QString::number(row + 1));
		}

		if (!m_bLockOffset)
		{
			m_StandOffsetLoadRobot.at(row).x = m_NozzlePosRobot.at(row).x - m_CameraPosRobot.at(row).x;
			m_StandOffsetLoadRobot.at(row).y = m_NozzlePosRobot.at(row).y - m_CameraPosRobot.at(row).y;
			GetmtfInstance()->UpdateSingleValue("conn1", "取料位标定参数", "OffsetX", QString::number(m_StandOffsetLoadRobot.at(row).x), "rowid", QString::number(row + 1));
			GetmtfInstance()->UpdateSingleValue("conn1", "取料位标定参数", "OffsetY", QString::number(m_StandOffsetLoadRobot.at(row).y), "rowid", QString::number(row + 1));
		}

		UpdataTable_StandOffsetLoadRobot();
	}
	else if (pTable->m_TableName == "StandPosImg")
	{
		if (column == 1)
		{
			m_StandImagePos.at(row).x = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "放料标准图像位置", "图像坐标X", value, "rowid", QString::number(row + 1));
		}
		else if (column == 2)
		{
			m_StandImagePos.at(row).y = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "放料标准图像位置", "图像坐标Y", value, "rowid", QString::number(row + 1));
		}
		else if (column == 3)
		{
			m_StandImagePos.at(row).R = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "放料标准图像位置", "角度R", value, "rowid", QString::number(row + 1));
		}
	}
	else if (pTable->m_TableName == "RotateCenterImg")
	{
		if (column == 1) {
			m_RotateCenterImg.at(row).x = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1","旋转中心","X坐标", value,"rowid",QString::number(row+1));
		}
		else if (column == 2) {
			m_RotateCenterImg.at(row).y = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "旋转中心", "Y坐标", value, "rowid", QString::number(row+1));
		}
	}
	else if (pTable->m_TableName == "ManualBCrobot")
	{
		if (column == 1)
		{
			m_ManualBCRobot.at(row).x = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "放料补偿", "X补偿", value, "rowid", QString::number(row + 1));
		}
		else if (column == 2)
		{
			m_ManualBCRobot.at(row).y = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "放料补偿", "Y补偿", value, "rowid", QString::number(row + 1));
		}
		else if (column == 3) {
			m_ManualBCRobot.at(row).R = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "放料补偿", "R补偿", value, "rowid", QString::number(row + 1));
		}
	}
	else if (pTable->m_TableName == "light")
	{
		if (column == 1)
		{
			m_LightIntensity.at(row).P0 = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "光源", "亮度", value, "rowid", QString::number(row + 1));
		}
	}
	else if (pTable->m_TableName == "LocationLimit")
	{
		if (column == 1) {
			m_OffsetLimit.at(row).StdX = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "防呆控制参数", "StdX", value, "rowid", QString::number(row + 1));
		}
		else if (column == 2) {
			m_OffsetLimit.at(row).StdY = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "防呆控制参数", "StdY", value, "rowid", QString::number(row + 1));
		}
		else if (column == 3) {
			m_OffsetLimit.at(row).StdR = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "防呆控制参数", "StdR", value, "rowid", QString::number(row + 1));
		}
		else if (column == 4) {
			m_OffsetLimit.at(row).X_N = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "防呆控制参数", "OffsetX_N", value, "rowid", QString::number(row + 1));
		}
		else if (column == 5) {
			m_OffsetLimit.at(row).X_P = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "防呆控制参数", "OffsetX_P", value, "rowid", QString::number(row + 1));
		}
		else if (column == 6) {
			m_OffsetLimit.at(row).Y_N = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "防呆控制参数", "OffsetY_N", value, "rowid", QString::number(row + 1));
		}
		else if (column == 7) {
			m_OffsetLimit.at(row).Y_P = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "防呆控制参数", "OffsetY_P", value, "rowid", QString::number(row + 1));
		}
		else if (column == 8) {
			m_OffsetLimit.at(row).R_N = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "防呆控制参数", "OffsetR_N", value, "rowid", QString::number(row + 1));
		}
		else if (column == 9) {
			m_OffsetLimit.at(row).R_P = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "防呆控制参数", "OffsetR_P", value, "rowid", QString::number(row + 1));
		}
	}
	else if (pTable->m_TableName == "ControlPara")
	{
		if (column == 1) {
			m_ControlPara.at(row).P0= value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "图像控制参数", "值", value, "rowid", QString::number(row + 1));
		}
	}
	else if (pTable->m_TableName == "CameraPara")
	{
		if (column == 1) {
			m_CameraPara.at(row).P0= value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "相机参数", "曝光", value, "rowid", QString::number(row + 1));
		}
		else if (column == 2) {
			m_CameraPara.at(row).P1 = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "相机参数", "增益", value, "rowid", QString::number(row + 1));
		}
		else if (column == 3) {
			m_CameraPara.at(row).P2 = value.toDouble();
			GetmtfInstance()->UpdateSingleValue("conn1", "相机参数", "伽马", value, "rowid", QString::number(row + 1));
		}
		InitCameraPara();
	}
}

void flexDlg::UpdataTable_StandOffsetLoadRobot()
{
	int TableNum = 0;
	disconnect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
	int row = 0;

	for (row = 0; row < m_CameraPosRobot.size(); row++)
	{
		m_NozzlePosRobot.at(row).x= GetmtfInstance()->QuerySingleValue2Double("conn1", "取料位标定参数", "吸头X", "rowid", QString::number(row + 1));
		m_NozzlePosRobot.at(row).y = GetmtfInstance()->QuerySingleValue2Double("conn1", "取料位标定参数", "吸头Y", "rowid", QString::number(row + 1));
		m_NozzlePosRobot.at(row).R = GetmtfInstance()->QuerySingleValue2Double("conn1", "取料位标定参数", "吸头R", "rowid", QString::number(row + 1));
	
		m_CameraPosRobot.at(row).x = GetmtfInstance()->QuerySingleValue2Double("conn1", "取料位标定参数", "相机X", "rowid", QString::number(row + 1));
		m_CameraPosRobot.at(row).y = GetmtfInstance()->QuerySingleValue2Double("conn1", "取料位标定参数", "相机Y", "rowid", QString::number(row + 1));
		m_CameraPosRobot.at(row).R = GetmtfInstance()->QuerySingleValue2Double("conn1", "取料位标定参数", "相机R", "rowid", QString::number(row + 1));

		m_StandOffsetLoadRobot.at(row).x = GetmtfInstance()->QuerySingleValue2Double("conn1", "取料位标定参数", "OffsetX", "rowid", QString::number(row + 1));
		m_StandOffsetLoadRobot.at(row).y = GetmtfInstance()->QuerySingleValue2Double("conn1", "取料位标定参数", "OffsetY", "rowid", QString::number(row + 1));
		m_StandOffsetLoadRobot.at(row).R = GetmtfInstance()->QuerySingleValue2Double("conn1", "取料位标定参数", "OffsetR", "rowid", QString::number(row + 1));
	}

	for (row = 0; row < m_CameraPosRobot.size(); row++)
	{
		m_pTable[TableNum]->setItemEx("吸嘴号", row, QString::number(row + 1));
		m_pTable[TableNum]->setItemEx("吸头X", row, QString::number(m_NozzlePosRobot.at(row).x));
		m_pTable[TableNum]->setItemEx("吸头Y", row, QString::number(m_NozzlePosRobot.at(row).y));
		m_pTable[TableNum]->setItemEx("吸头R", row, QString::number(m_NozzlePosRobot.at(row).R));

		m_pTable[TableNum]->setItemEx("相机X", row, QString::number(m_CameraPosRobot.at(row).x));
		m_pTable[TableNum]->setItemEx("相机Y", row, QString::number(m_CameraPosRobot.at(row).y));
		m_pTable[TableNum]->setItemEx("相机R", row, QString::number(m_CameraPosRobot.at(row).R));

		m_pTable[TableNum]->setItemEx("offsetX", row, QString::number(m_StandOffsetLoadRobot.at(row).x));
		m_pTable[TableNum]->setItemEx("offsetY", row, QString::number(m_StandOffsetLoadRobot.at(row).y));

		m_pTable[TableNum]->SetFlags("offsetX", row, 0);
		m_pTable[TableNum]->SetFlags("offsetY", row, 0);

		if (row==0)
		{
			m_pTable[TableNum]->setItemEx("备注", row, "以下取料偏移");
		}
		if (/*4<=row&& */m_bLockOffset)
		{
			m_CameraPosRobot.at(row).x = m_NozzlePosRobot.at(row).x - m_StandOffsetLoadRobot.at(row).x;
			m_CameraPosRobot.at(row).y = m_NozzlePosRobot.at(row).y - m_StandOffsetLoadRobot.at(row).y;
			//m_CameraPosRobot.at(row).angle = m_NozzlePosRobot.at(row).angle - m_StandOffsetLoadRobot.at(row).angle;
			GetmtfInstance()->UpdateSingleValue("conn1", "取料位标定参数", "相机X",QString::number(m_CameraPosRobot.at(row).x), "rowid", QString::number(row + 1));
			GetmtfInstance()->UpdateSingleValue("conn1", "取料位标定参数", "相机Y", QString::number(m_CameraPosRobot.at(row).y), "rowid", QString::number(row + 1));

			m_pTable[TableNum]->setItemEx("相机X", row, QString::number(m_CameraPosRobot.at(row).x));
			m_pTable[TableNum]->setItemEx("相机Y", row, QString::number(m_CameraPosRobot.at(row).y));
			m_pTable[TableNum]->setItemEx("相机R", row, QString::number(m_CameraPosRobot.at(row).R));

			m_pTable[TableNum]->setItemEx("offsetX", row, QString::number(m_StandOffsetLoadRobot.at(row).x));
			m_pTable[TableNum]->setItemEx("offsetY", row, QString::number(m_StandOffsetLoadRobot.at(row).y));

			m_pTable[TableNum]->SetFlags("相机X", row, 0);
			m_pTable[TableNum]->SetFlags("相机Y", row, 0);
			m_pTable[TableNum]->SetFlags("相机R", row, 0);

			m_pTable[TableNum]->SetFlags("offsetX", row, 0);
			m_pTable[TableNum]->SetFlags("offsetY", row, 0);
		}
	}
	connect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
}

void flexDlg::UpdataTable_StandImgPos()
{
	int TableNum = 1;
	disconnect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
	int row = 0;

	for (row = 0; row < m_StandImagePos.size(); row++)
	{
		m_StandImagePos.at(row).x = GetmtfInstance()->QuerySingleValue2Double("conn1", "放料标准图像位置", "图像坐标X", "rowid", QString::number(row + 1));
		m_StandImagePos.at(row).y = GetmtfInstance()->QuerySingleValue2Double("conn1", "放料标准图像位置", "图像坐标Y", "rowid", QString::number(row + 1));
		m_StandImagePos.at(row).R = GetmtfInstance()->QuerySingleValue2Double("conn1", "放料标准图像位置", "角度R", "rowid", QString::number(row + 1));
	}

	for (row = 0; row < m_StandImagePos.size(); row++)
	{
		m_pTable[TableNum]->setItemEx("放料顺序", row, QString::number(row + 1));
		m_pTable[TableNum]->setItemEx("图像坐标X", row, QString::number(m_StandImagePos.at(row).x));
		m_pTable[TableNum]->setItemEx("图像坐标Y", row, QString::number(m_StandImagePos.at(row).y));
		m_pTable[TableNum]->setItemEx("角度R", row, QString::number(m_StandImagePos.at(row).R));


		if (row == 0)
		{
			m_pTable[TableNum]->setItemEx("备注", row, "本行及以下是载盘放料标准位");
		}
		//else if (row == 6)
		//{
		//	m_pTable[TableNum]->setItemEx("备注", row, "本行及以下放料标准位");
		//}
	}
	connect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
}

void flexDlg::UpdataTable_RotateCenter()
{
	int TableNum = 2;
	disconnect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
	int row = 0;

	for (row = 0; row < m_RotateCenterImg.size(); row++)
	{
		m_RotateCenterImg.at(row).x = GetmtfInstance()->QuerySingleValue2Double("conn1", "旋转中心", "X坐标", "rowid",QString::number(row+1));
		m_RotateCenterImg.at(row).y = GetmtfInstance()->QuerySingleValue2Double("conn1", "旋转中心", "Y坐标", "rowid", QString::number(row + 1));
	}

	for (row = 0; row < m_RotateCenterImg.size(); row++)
	{
		m_pTable[TableNum]->setItemEx("吸嘴号", row, QString::number(row + 1));
		m_pTable[TableNum]->setItemEx("图像坐标X", row, QString::number(m_RotateCenterImg.at(row).x));
		m_pTable[TableNum]->setItemEx("图像坐标Y", row, QString::number(m_RotateCenterImg.at(row).y));
		if (row == 0)
		{
			m_pTable[TableNum]->setItemEx("备注", row, "手抓旋转中心");
		}
		//else if (row == 6)
		//{
		//	m_pTable[TableNum]->setItemEx("备注", row, "本行及以下放料旋转中心");
		//}
	}
	connect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
}

void flexDlg::UpdataTable_ManualBC()
{
	int TableNum = 3;
	disconnect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
	int row = 0;

	for (row = 0; row < m_ManualBCRobot.size(); row++)
	{
		m_ManualBCRobot.at(row).x = GetmtfInstance()->QuerySingleValue2Double("conn1", "放料补偿", "X补偿", "rowid", QString::number(row + 1));
		m_ManualBCRobot.at(row).y = GetmtfInstance()->QuerySingleValue2Double("conn1", "放料补偿", "Y补偿", "rowid", QString::number(row + 1));
		m_ManualBCRobot.at(row).R = GetmtfInstance()->QuerySingleValue2Double("conn1", "放料补偿", "R补偿", "rowid", QString::number(row + 1));
	}

	for (row = 0; row < m_ManualBCRobot.size(); row++)
	{
		m_pTable[TableNum]->setItemEx("放料顺序", row, QString::number(row + 1));
		m_pTable[TableNum]->setItemEx("X补偿", row, QString::number(m_ManualBCRobot.at(row).x));
		m_pTable[TableNum]->setItemEx("Y补偿", row, QString::number(m_ManualBCRobot.at(row).y));
		m_pTable[TableNum]->setItemEx("R补偿", row, QString::number(m_ManualBCRobot.at(row).R)); 

		if (row == 0)
		{
			m_pTable[TableNum]->setItemEx("备注", row, "本行及以下是载盘放料位补偿");
		}
		//else if (row == 6)
		//{
		//	m_pTable[TableNum]->setItemEx("备注", row, "本行及以下是放料补偿");
		//}
	}
	connect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
}

void flexDlg::UpdataTable_light()
{
	int TableNum = 4;
	disconnect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
	int row = 0;
	for (row = 0; row < m_LightIntensity.size(); row++)
	{
		m_LightIntensity.at(row).P0 = GetmtfInstance()->QuerySingleValue2Double("conn1", "光源", "亮度", "rowid", QString::number(row + 1));
	}

	for (row = 0; row < m_LightIntensity.size(); row++)
	{
		m_pTable[TableNum]->setItemEx("位置ID", row, QString::number(row + 1));
		m_pTable[TableNum]->setItemEx("亮度", row, QString::number(m_LightIntensity.at(row).P0));

		if (row == 0)
		{
			m_pTable[TableNum]->setItemEx("备注", row, "上相机条光1");
		}
		else if (row == 1)
		{
			m_pTable[TableNum]->setItemEx("备注", row, "上相机条光2");
		}
		else if (row == 2)
		{
			m_pTable[TableNum]->setItemEx("备注", row, "下相机条光1");
		}
		else if (row == 3)
		{
			m_pTable[TableNum]->setItemEx("备注", row, "下相机条光2");
		}
		else if (row == 4)
		{
			m_pTable[TableNum]->setItemEx("备注", row, "防呆光源");
		}
		else if (row == 5)
		{
			m_pTable[TableNum]->setItemEx("备注", row, "预留");
		}
		else if (row == 6)
		{
			m_pTable[TableNum]->setItemEx("备注", row, "预留");
		}


	}
	connect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
}

void flexDlg::UpdataTable_LocationLimtPara()
{
	int TableNum = 5;
	disconnect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
	int row = 0;

	for (row = 0; row < m_OffsetLimit.size(); row++)
	{
		m_OffsetLimit.at(row).StdX = GetmtfInstance()->QuerySingleValue2Double("conn1", "防呆控制参数", "StdX", "rowid", QString::number(row + 1));
		m_OffsetLimit.at(row).StdY = GetmtfInstance()->QuerySingleValue2Double("conn1", "防呆控制参数", "StdY", "rowid", QString::number(row + 1));
		m_OffsetLimit.at(row).StdR = GetmtfInstance()->QuerySingleValue2Double("conn1", "防呆控制参数", "StdR", "rowid", QString::number(row + 1));
	
		m_OffsetLimit.at(row).X_N = GetmtfInstance()->QuerySingleValue2Double("conn1", "防呆控制参数", "OffsetX_N", "rowid", QString::number(row + 1));
		m_OffsetLimit.at(row).X_P = GetmtfInstance()->QuerySingleValue2Double("conn1", "防呆控制参数", "OffsetX_P", "rowid", QString::number(row + 1));

		m_OffsetLimit.at(row).Y_N = GetmtfInstance()->QuerySingleValue2Double("conn1", "防呆控制参数", "OffsetY_N", "rowid", QString::number(row + 1));
		m_OffsetLimit.at(row).Y_P = GetmtfInstance()->QuerySingleValue2Double("conn1", "防呆控制参数", "OffsetY_P", "rowid", QString::number(row + 1));

		m_OffsetLimit.at(row).R_N = GetmtfInstance()->QuerySingleValue2Double("conn1", "防呆控制参数", "OffsetR_N", "rowid", QString::number(row + 1));
		m_OffsetLimit.at(row).R_P = GetmtfInstance()->QuerySingleValue2Double("conn1", "防呆控制参数", "OffsetR_P", "rowid", QString::number(row + 1));	
	}

	for (row = 0; row < m_OffsetLimit.size(); row++)
	{
		m_pTable[TableNum]->setItemEx("载具穴位号", row, QString::number(row + 1));
		m_pTable[TableNum]->setItemEx("StdX", row, QString::number(m_OffsetLimit.at(row).StdX));
		m_pTable[TableNum]->setItemEx("StdY", row, QString::number(m_OffsetLimit.at(row).StdY));
		m_pTable[TableNum]->setItemEx("StdR", row, QString::number(m_OffsetLimit.at(row).StdR));
		m_pTable[TableNum]->setItemEx("X-", row, QString::number(m_OffsetLimit.at(row).X_N));
		m_pTable[TableNum]->setItemEx("X+", row, QString::number(m_OffsetLimit.at(row).X_P));
		m_pTable[TableNum]->setItemEx("Y-", row, QString::number(m_OffsetLimit.at(row).Y_N));
		m_pTable[TableNum]->setItemEx("Y+", row, QString::number(m_OffsetLimit.at(row).Y_P));
		m_pTable[TableNum]->setItemEx("R-", row, QString::number(m_OffsetLimit.at(row).R_N));
		m_pTable[TableNum]->setItemEx("R+", row, QString::number(m_OffsetLimit.at(row).R_P));
	}
	connect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);

}

void flexDlg::UpdataTable_ControlPara()
{
	int TableNum = 6;
	disconnect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
	int row = 0;
	for (row = 0; row < m_ControlPara.size(); row++)
	{
		m_ControlPara.at(row).P0= GetmtfInstance()->QuerySingleValue2Double("conn1", "图像控制参数","值","rowid", QString::number(row + 1));
	}
	for (row = 0; row < m_ControlPara.size(); row++)
	{
		m_pTable[TableNum]->setItemEx("位置ID", row, QString::number(row + 1));
		m_pTable[TableNum]->setItemEx("值", row, QString::number(m_ControlPara.at(row).P0));

		if (row == 0)
		{
			m_pTable[TableNum]->setItemEx("备注", row, "取料拍照");
		}
		else if (row == 1)
		{
			m_pTable[TableNum]->setItemEx("备注", row, "下相机拍照");
		}
		else if (row == 2)
		{
			m_pTable[TableNum]->setItemEx("备注", row, "防呆拍照");
		}
	}
	connect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
}

void flexDlg::UpdataTable_CameraPara()
{
	int TableNum = 7;
	disconnect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
	int row = 0;
	for (row = 0; row < m_CameraPara.size(); row++)
	{
		m_CameraPara.at(row).P0 = GetmtfInstance()->QuerySingleValue2Double("conn1", "相机参数", "曝光", "rowid", QString::number(row + 1));
		m_CameraPara.at(row).P1 = GetmtfInstance()->QuerySingleValue2Double("conn1", "相机参数", "增益", "rowid", QString::number(row + 1));
		m_CameraPara.at(row).P2 = GetmtfInstance()->QuerySingleValue2Double("conn1", "相机参数", "伽马", "rowid", QString::number(row + 1));
	}

	for (row = 0; row < m_CameraPara.size(); row++)
	{
		m_pTable[TableNum]->setItemEx("相机ID", row, QString::number(row + 1));
		m_pTable[TableNum]->setItemEx("曝光", row, QString::number(m_CameraPara.at(row).P0));
		m_pTable[TableNum]->setItemEx("增益", row, QString::number(m_CameraPara.at(row).P1));
		m_pTable[TableNum]->setItemEx("伽马", row, QString::number(m_CameraPara.at(row).P2));

		if (row == 0)
		{
			m_pTable[TableNum]->setItemEx("备注", row, "扫码相机");
		}
		else if (row == 1)
		{
			m_pTable[TableNum]->setItemEx("备注", row, "下相机");
		}
		else if (row == 2)
		{
			m_pTable[TableNum]->setItemEx("备注", row, "防呆相机");
		}
	}
	connect(m_pTable[TableNum], &MyTableWidget::cellChanged, this, &flexDlg::OnEditTable);
	InitCameraPara();//
}

void flexDlg::OnPushButton()
{
	QPushButton* pbtn = qobject_cast<QPushButton*>(sender());
	QString btnName = pbtn->objectName();
	if (btnName == "btn_send_plc")
	{
		int i = ui->cbx_cmd_plc->currentIndex();
		QString connName = ui->cbx_ConnName_plc->currentText();
		StFixedData data = m_pflexComm->Str2Cmd(m_vecPlcCmdSet.at(i));
		m_pflexComm->SendData(data, connName);
		ui->textBrowser_dispCmd->append((m_pflexComm->Cmd2Str(data)).toStdString().data());
	}
	else if (btnName == "btn_FreshCmd_plc")
	{
		ReadCmdPlc();
	}
	else if (btnName == "btn_load_cmd")
	{
		m_PlcCmdPath = QFileDialog::getOpenFileName(0, "选择命令文件", Icg::getPlcCmdDirPath(), "*.txt");
		if (!m_PlcCmdPath.contains(".txt"))  return;
		ui->textBrowser_CmdPath->setText(m_PlcCmdPath);
	}
	else if (btnName == "btn_openfolder_cmd")
	{
		QDesktopServices::openUrl(QUrl::fromLocalFile(m_PlcCmdPath));
	}
}

void flexDlg::InitFlexPara()
{
	m_pwnd[0] = IPF::GetSetDispFormMap()["Form_0"];
	m_pwnd[1] = IPF::GetSetDispFormMap()["Form_1"];
	m_pwnd[2] = IPF::GetSetDispFormMap()["Form_2"];
	m_pwnd[3] = IPF::GetSetDispFormMap()["Form_3"];
	m_pwnd[4] = IPF::GetSetDispFormMap()["Form_4"];
	m_pwnd[5] = IPF::GetSetDispFormMap()["Form_5"];
	m_pwnd[6] = IPF::GetSetDispFormMap()["Form_6"];

	LoadCalibFile();
}


//收到客户端请求， 服务端回复客户端请求时触发信号：=================================================================================================
void flexDlg::OnRecvRegist(StFixedData data, bool bCheckTimeOut /*= false*/)
{
	m_pflexComm->ReRegist(data, 0);
	m_pflexDispDlg->LightStatus(m_pflexDispDlg->m_pBtnStatePLc, 1);
	//m_TimerId_heart = startTimer(1000 * Icg::getIntervalHeart());

	QString text = QString((char*)data.msg3);
	int count = ui->cbx_ConnName_plc->count();
	bool bfind = false;
	for (int i = 0; i < count; i++)
	{
		if (text == ui->cbx_ConnName_plc->itemText(i))
		{
			bfind = true;
		}
	}
	if (bfind)	ui->cbx_ConnName_plc->addItem(text);
	ui->cbx_ConnName_plc->setCurrentText(text);
}

void flexDlg::OnRecvRecvWarning(StFixedData data, bool bCheckTimeOut /*= false*/)
{
	int WarningNum = data.Param0;//报警编号
	int iSWarning = data.Param1;//0是发生报警，1是消除报警
	m_pflexComm->ReWarning(data, 0);
	LOG_INFO(glogger, MultUtf82Mult2("报警请求回复完成"));
	auto fun = [=] {
		QDateTime DateTime = QDateTime::currentDateTime();
		QString strDateTime = DateTime.toString("yyyy-MM-dd_hh_mm_ss");
		QString strDate = DateTime.date().toString("yyyy-MM-dd");
		//QString strTime = DateTime.time().toString("hh_mm_ss");
		QString strTimeDot = DateTime.time().toString("hh:mm:ss");
		QString connName = DateTime.time().toString("hhmmsszzz");
		m_pflexdb->CreateflexDataConnection(connName);
		lockup(m_WritePLCWarningCsvMutex);
		QString FolderPath = m_PlcLogDataFolderPath;
		if (!GetmtfInstance()->isFolderExist(FolderPath))
		{
			GetmtfInstance()->CreateExteriorFolder(FolderPath);
		}
		QString filePath = FolderPath + "/" + strDate + ".csv";
		if (!GetmtfInstance()->isFileExist(filePath))
		{
			WritePLCWarningCsvHeader(filePath);
		}
		if (iSWarning == 0)
		{
			WritePLCWarningCsvData(strTimeDot, WarningNum, m_WarningMap[WarningNum], filePath);
			m_pflexdb->WriteLogDB(connName, WarningNum, m_WarningMap[WarningNum]);
			LOG_INFO(glogger, MultUtf82Mult2("PLC发起编号") << WarningNum << MultUtf82Mult2("的报警：") << MultUtf82Mult(m_WarningMap[WarningNum]));
		}
		else
		{
			WritePLCWarningCsvData(strTimeDot,0,"PLC报警解除", filePath);
			m_pflexdb->WriteLogDB(connName,0, "PLC报警解除");
			LOG_INFO(glogger, MultUtf82Mult2("PLC报警解除"));
		}
		m_pflexdb->removeConnection(connName);
	};
	gthpool->AddTask(fun);
}

void flexDlg::OnRecvTestResult(StFixedData data, bool bCheckTimeOut /*= false*/)
{
	//QString result = (char*)data.msg;
	//for (int i=0;i<24;i++)
	//{
	//	QString res = result.at(i);
	//	m_pflexDispDlg->DutResultStatus(m_pflexDispDlg->m_pDut[i], res.toInt(),"");
	//}
	INT32 result = data.Param0;
	for (int i = 0; i < 24; i++)
	{
		int bitValue = GetBit(result, i);
		m_pflexDispDlg->DutResultStatus(m_pflexDispDlg->m_pDut[i], bitValue, "");
		//m_output++;
		//m_uphCount++;
	}

	//for (int i = 23,j=0; i >=0; i--,j++)
	//{
	//	int bitValue = GetBit(result, i);
	//	m_pflexDispDlg->DutResultStatus(m_pflexDispDlg->m_pDut[j], bitValue, "");
	//}

	//ShowCountInfo(m_output, m_uphCount);
	//gthpool->AddTask();

	m_pflexComm->ReTestResult(data, 0);
	LOG_INFO(glogger, MultUtf82Mult2("回复测试结果请求完成"));
}

void flexDlg::OnRecvEquipmentState(StFixedData data, bool bCheckTimeOut /*= false*/)
{
	m_pflexComm->ReEquipmentState(data, 0);
	LOG_INFO(glogger, MultUtf82Mult2("设备状态更新请求的回复完成"));

	INT32 result = data.Param0;
	if (result==0)//工作中
	{
		m_pflexDispDlg->m_bWorking = true;
		m_pflexDispDlg->m_bWarning = false;
		m_pflexDispDlg->m_bWaitting = false;
	} 
	else if (result == 1)//报警
	{
		m_pflexDispDlg->m_bWorking = false;
		m_pflexDispDlg->m_bWarning = true;
		m_pflexDispDlg->m_bWaitting = false;
	}
	else if (result == 2)//待料
	{
		m_pflexDispDlg->m_bWorking = false;
		m_pflexDispDlg->m_bWarning = false;
		m_pflexDispDlg->m_bWaitting = true;
	}

}

bool  flexDlg::GetImg(sptr<HObject>& obj, QString CameraName, int CameraIndex, int PictureIndex, int GroupIndex)
{
	if (!m_bSimulate && (Icg::getControlNum() != 0))//光源
	{
		if ((pSimulateCam != nullptr) || (pSimulateCam->GetSiCamMap()[CameraIndex][PictureIndex] != nullptr))
		{
			MessageBoxTip("请切换仿真模式");
			return false;
		}
		int channel[2];
		int time[2] = { 50,50 };
		if (GroupIndex <= 1)
		{
			channel[0] = m_vecLightChannel.at(0);
			channel[1] = m_vecLightChannel.at(1);
			Icg::getNameControlMap()[CTRL_NAME_0]->SoftwareMultiTrigger(channel, time, 2);
		}
		else if (!m_bAlwaysBright)
		{
			channel[0] = m_vecLightChannel.at(2);
			channel[1] = m_vecLightChannel.at(3);
			Icg::getNameControlMap()[CTRL_NAME_0]->SoftwareMultiTrigger(channel, time, 2);
		}
	}
	//相机=======================================================================================
	if (!m_bSimulate)
	{
		if ((pSimulateCam != nullptr) || (pSimulateCam->GetSiCamMap()[CameraIndex][PictureIndex] != nullptr))
		{
			MessageBoxTip("请切换仿真模式");
			return false;
		}
		Icg::getNameCameraMap()[CameraName]->GetSingleImage(obj);
	}
	else
	{
		if (pSimulateCam == nullptr || pSimulateCam->GetSiCamMap()[CameraIndex][PictureIndex] == nullptr)
		{
			MessageBoxTip("请先打开仿真相机");
			return false;
		}
		pSimulateCam->GetSiCamMap()[CameraIndex][PictureIndex]->GetSingleImage(obj);
	}
	return true;
}

void flexDlg::OnRecvPhotograph(StFixedData data, bool bCheckTimeOut /*= false*/)
{
	if (data.Param0 == 1)//取料第一组吸嘴
	{
		auto fun = [=] {
			auto start = GetmtfInstance()->GetTimeNow();
			int GroupImgIndex = 0;
			if (GetImg(m_GroupImg[GroupImgIndex], CAM_NAME_0, 0, 0, GroupImgIndex)) m_pflexComm->RePhotograph(data, 0);
			else {
				m_pflexComm->RePhotograph(data, 1);
				return;
			}
			sptr<HObject> nozzleImg[3];
			nozzleImg[0] = mksptr<HObject>();
			nozzleImg[1] = mksptr<HObject>();
			nozzleImg[2] = mksptr<HObject>();
			sptr<HObject> Imgcode[3];
			Imgcode[0] = mksptr<HObject>();
			Imgcode[1] = mksptr<HObject>();
			Imgcode[2] = mksptr<HObject>();

			int nozzleIndex = -1;//0-2
			m_hdev->CropImage(*m_GroupImg[GroupImgIndex], *m_NnozzleImgRoi[0], *m_NnozzleImgRoi[1], *m_NnozzleImgRoi[2], *nozzleImg[0], *nozzleImg[1], *nozzleImg[2], *Imgcode[0], *Imgcode[1], *Imgcode[2], GroupImgIndex);
			_ImgRsult temp[3];
			//int nozzleIndex = -1;//0-2
			std::future<_ImgRsult> res[3];
			for (int i = 0; i < 3; ++i)
			{
				if (i == 0 && data.Param1 == 1) continue;
				if (i == 1 && data.Param2 == 1) continue;
				if (i == 2 && data.Param3 == 1) continue;

				try
				{
					nozzleIndex = i;
					res[i] = gthpool->AddTask(std::bind(&flexDlg::ImgProcess, this, data, nozzleIndex,0,m_GroupImg[GroupImgIndex], nozzleImg[nozzleIndex], Imgcode[nozzleIndex]));
				}
				catch (...)
				{
					LOG_DEBUG(glogger, MultUtf82Mult2("取料") << i + 1 << MultUtf82Mult2("号吸嘴Task任务@ImgProcess出错！"));
					temp[i].data.P0 = (int)ErrorCode::LocationFail;
				}
			}

			if (data.Param1 == 0) temp[0] = res[0].get();
			if (data.Param2 == 0) temp[1] = res[1].get();
			if (data.Param3 == 0) temp[2] = res[2].get();

			if (m_bEmpyRun)
			{
				//m_pflexComm->TakeDutResult(data.Param0,
				//	temp[0].data.erroCode, temp[1].data.erroCode, temp[2].data.erroCode,
				//	0, //本条命令的erroCode
				//	temp[0].strCode, temp[1].strCode, temp[2].strCode);

				//emit postShowData(data.Param0, 0, 0, 0);
			}
			else
			{
				m_pflexComm->TakeDutResult(GroupImgIndex+1,
					temp[0].data.P0, temp[1].data.P0, temp[2].data.P0,
					0, //本条命令的erroCode
					temp[0].strCode, temp[1].strCode, temp[2].strCode);
				//m_pflexComm->ReTakeDut(data, temp.data.x, temp.data.y, temp.data.angle * 1000, temp.data.erroCode, temp.strCode);
				//m_pflexComm->ReTakeDut(data, temp.data.x, temp.data.y, 0, temp.data.erroCode, temp.strCode);//屏蔽取料角度
				//if (temp.data.erroCode != 0) return;
				//emit postShowData(data.Param0, temp.data.x, temp.data.y, temp.data.angle);
			}
			auto end = GetmtfInstance()->GetTimeNow();
			double durationTime = GetmtfInstance()->durationTime(end, start, TimeType::second);
			LOG_DEBUG(glogger, MultUtf82Mult2("取料第") << 1 << MultUtf82Mult2("组吸嘴图像处理总耗时：") << durationTime);
		};
		gthpool->AddTask(fun);

	}
	else if (data.Param0 == 2)//取料第二组吸嘴
	{
		auto fun = [=] {
			auto start = GetmtfInstance()->GetTimeNow();
			int GroupImgIndex = 1;
			if (GetImg(m_GroupImg[GroupImgIndex], CAM_NAME_0, 0, 1, GroupImgIndex)) m_pflexComm->RePhotograph(data, 0);
			else {
				m_pflexComm->RePhotograph(data, 1);
				return;
			}
			sptr<HObject> nozzleImg[3];
			nozzleImg[0] = mksptr<HObject>();
			nozzleImg[1] = mksptr<HObject>();
			nozzleImg[2] = mksptr<HObject>();
			sptr<HObject> Imgcode[3];
			Imgcode[0] = mksptr<HObject>();
			Imgcode[1] = mksptr<HObject>();
			Imgcode[2] = mksptr<HObject>();
			int nozzleIndex = -1;//0-2
			m_hdev->CropImage(*m_GroupImg[GroupImgIndex], *m_NnozzleImgRoi[3], *m_NnozzleImgRoi[4], *m_NnozzleImgRoi[5], *nozzleImg[0], *nozzleImg[1], *nozzleImg[2], *Imgcode[0], *Imgcode[1], *Imgcode[2], GroupImgIndex);
			_ImgRsult temp[3];
			//int nozzleIndex = -1;//0-2
			std::future<_ImgRsult> res[3];
			for (int i = 0; i < 3; ++i)
			{
				if (i == 0 && data.Param1 == 1) continue;
				if (i == 1 && data.Param2 == 1) continue;
				if (i == 2 && data.Param3 == 1) continue;
				try
				{
					nozzleIndex = i;
					res[i] = gthpool->AddTask(std::bind(&flexDlg::ImgProcess, this, data, nozzleIndex,0, m_GroupImg[GroupImgIndex], nozzleImg[nozzleIndex], Imgcode[nozzleIndex]));
				}
				catch (...)
				{
					LOG_DEBUG(glogger, MultUtf82Mult2("取料") << i + 4 << MultUtf82Mult2("号吸嘴Task任务@ImgProcess出错！"));
					temp[i].data.P0 = (int)ErrorCode::LocationFail;
				}
			}
			if (data.Param1 == 0) temp[0] = res[0].get();
			if (data.Param2 == 0) temp[1] = res[1].get();
			if (data.Param3 == 0) temp[2] = res[2].get();

			if (m_bEmpyRun)
			{
				//m_pflexComm->TakeDutResult(data.Param0,
				//	temp[0].data.erroCode, temp[1].data.erroCode, temp[2].data.erroCode,
				//	0, //本条命令的erroCode
				//	temp[0].strCode, temp[1].strCode, temp[2].strCode);

				//emit postShowData(data.Param0, 0, 0, 0);
			}
			else
			{
				m_pflexComm->TakeDutResult(GroupImgIndex+1,
					temp[0].data.P0, temp[1].data.P0, temp[2].data.P0,
					0, //本条命令的erroCode
					temp[0].strCode, temp[1].strCode, temp[2].strCode);
				//m_pflexComm->ReTakeDut(data, temp.data.x, temp.data.y, temp.data.angle * 1000, temp.data.erroCode, temp.strCode);
				//m_pflexComm->ReTakeDut(data, temp.data.x, temp.data.y, 0, temp.data.erroCode, temp.strCode);//屏蔽取料角度
				//if (temp.data.erroCode != 0) return;
				//emit postShowData(data.Param0, temp.data.x, temp.data.y, temp.data.angle);
			}
			auto end = GetmtfInstance()->GetTimeNow();
			double durationTime = GetmtfInstance()->durationTime(end, start, TimeType::second);
			LOG_DEBUG(glogger, MultUtf82Mult2("取料第") << 2<< MultUtf82Mult2("组吸嘴图像处理总耗时：") << durationTime);
		};
		gthpool->AddTask(fun);
	}
	else if (data.Param0 == 3)//放料第一组吸嘴
	{
		auto fun = [=] {
			auto start = GetmtfInstance()->GetTimeNow();
			int GroupImgIndex = 2;
			if (GetImg(m_GroupImg[GroupImgIndex], CAM_NAME_1, 1, 0, GroupImgIndex)) m_pflexComm->RePhotograph(data, 0);
			else {
				m_pflexComm->RePhotograph(data, 1);
				return;
			}
			sptr<HObject> nozzleImg[3];
			nozzleImg[0] = mksptr<HObject>();
			nozzleImg[1] = mksptr<HObject>();
			nozzleImg[2] = mksptr<HObject>();
			sptr<HObject> Imgcode[3];
			Imgcode[0] = mksptr<HObject>();
			Imgcode[1] = mksptr<HObject>();
			Imgcode[2] = mksptr<HObject>();
			int nozzleIndex = -1;//0-2
			m_hdev->CropImage(*m_GroupImg[GroupImgIndex], *m_NnozzleImgRoi[6], *m_NnozzleImgRoi[7], *m_NnozzleImgRoi[8], *nozzleImg[0], *nozzleImg[1], *nozzleImg[2], *Imgcode[0], *Imgcode[1], *Imgcode[2], GroupImgIndex);
			_ImgRsult temp[3];

			std::future<_ImgRsult> res[3];
			for (int i = 0; i < 3; ++i)
			{
				//if (i == 0 && data.Param1 == 1) continue;
				//if (i == 1 && data.Param2 == 1) continue;
				//if (i == 2 && data.Param3 == 1) continue;

				int stdSlotIndex = -1;
				if (i == 0){
					if(data.Param1 == 0) stdSlotIndex = data.Param4;
					else continue;
				}else if (i == 1) {
					if (data.Param2 == 0) stdSlotIndex = data.Param5;
					else continue;
				}
				else if (i == 2) {
					if (data.Param3 == 0) stdSlotIndex = data.Param6;
					else continue;
				}

				try
				{
					nozzleIndex = i;
					res[i] = gthpool->AddTask(std::bind(&flexDlg::ImgProcess, this, data, nozzleIndex, stdSlotIndex, m_GroupImg[GroupImgIndex], nozzleImg[nozzleIndex], Imgcode[nozzleIndex]));
				}
				catch (...)
				{
					LOG_DEBUG(glogger, MultUtf82Mult2("放料") << i + 1 << MultUtf82Mult2("号吸嘴Task任务@ImgProcess出错！"));
					temp[i].data.P0 = (int)ErrorCode::LocationFail;
				}
			}
			if (data.Param1 == 0) temp[0] = res[0].get();
			if (data.Param2 == 0) temp[1] = res[1].get();
			if (data.Param3 == 0) temp[2] = res[2].get();

			if (m_bEmpyRun)
			{
				//emit postShowData(data.Param0, 0, 0, 0);
			}
			else
			{
				m_pflexComm->PutDutResult(GroupImgIndex + 1,
					temp[0].data.P0, temp[1].data.P0, temp[2].data.P0,
					temp[0].data.x, temp[0].data.y, Round_off(temp[0].data.R, 2) * 1000,
					temp[1].data.x, temp[1].data.y, Round_off(temp[1].data.R, 2) * 1000,
					temp[2].data.x, temp[2].data.y, Round_off(temp[2].data.R, 2) * 1000,
					0//本条命令的erroCode
				);

				//m_pflexComm->ReTakeDut(data, temp.data.x, temp.data.y, temp.data.angle * 1000, temp.data.erroCode, temp.strCode);
				//m_pflexComm->ReTakeDut(data, temp.data.x, temp.data.y, 0, temp.data.erroCode, temp.strCode);//屏蔽取料角度
				for (int i = 0; i < 3; ++i)
				{
					if (temp[i].data.P0 == 0)
						emit postShowData("放料" + QString::number(i + 1), "放料", temp[i].data.x, temp[i].data.y, Round_off(temp[i].data.R, 2));
					else m_iTotalPositingFail++;
				}
			}
			auto end = GetmtfInstance()->GetTimeNow();
			double durationTime = GetmtfInstance()->durationTime(end, start, TimeType::second);
			LOG_DEBUG(glogger, MultUtf82Mult2("放料第") << 1 << MultUtf82Mult2("组吸嘴图像处理总耗时：") << durationTime);
		};
		gthpool->AddTask(fun);
	}
	else if (data.Param0 == 4)//放料第二组吸嘴
	{
		auto fun = [=] {
			auto start = GetmtfInstance()->GetTimeNow();
			int GroupImgIndex = 3;
			if (GetImg(m_GroupImg[GroupImgIndex], CAM_NAME_1, 1, 1, GroupImgIndex)) m_pflexComm->RePhotograph(data, 0);
			else {
				m_pflexComm->RePhotograph(data, 1);
				return;
			}
			sptr<HObject> nozzleImg[3];
			nozzleImg[0] = mksptr<HObject>();
			nozzleImg[1] = mksptr<HObject>();
			nozzleImg[2] = mksptr<HObject>();
			sptr<HObject> Imgcode[3];
			Imgcode[0] = mksptr<HObject>();
			Imgcode[1] = mksptr<HObject>();
			Imgcode[2] = mksptr<HObject>();
			int nozzleIndex = -1;//0-2
			m_hdev->CropImage(*m_GroupImg[GroupImgIndex], *m_NnozzleImgRoi[9], *m_NnozzleImgRoi[10], *m_NnozzleImgRoi[11], *nozzleImg[0], *nozzleImg[1], *nozzleImg[2], *Imgcode[0], *Imgcode[1], *Imgcode[2], GroupImgIndex);
			_ImgRsult temp[3];
			//int nozzleIndex = -1;//0-2
			std::future<_ImgRsult> res[3];
			for (int i = 0; i < 3; ++i)
			{
				//if (i == 0 && data.Param1 == 1) continue;
				//if (i == 1 && data.Param2 == 1) continue;
				//if (i == 2 && data.Param3 == 1) continue;

				int stdSlotIndex = -1;
				if (i == 0) {
					if (data.Param1 == 0) stdSlotIndex = data.Param7;
					else continue;
				}
				else if (i == 1) {
					if (data.Param2 == 0) stdSlotIndex = data.Param8;
					else continue;
				}
				else if (i == 2) {
					if (data.Param3 == 0) stdSlotIndex = data.Param9;
					else continue;
				}

				try
				{
					nozzleIndex = i;
					res[i] = gthpool->AddTask(std::bind(&flexDlg::ImgProcess, this, data, nozzleIndex, stdSlotIndex, m_GroupImg[GroupImgIndex], nozzleImg[nozzleIndex], Imgcode[nozzleIndex]));
				}
				catch (...)
				{
					LOG_DEBUG(glogger, MultUtf82Mult2("放料") << i + 4 << MultUtf82Mult2("号吸嘴Task任务@ImgProcess出错！"));
					temp[i].data.P0 = (int)ErrorCode::LocationFail;
				}
			}
			if (data.Param1 == 0) temp[0] = res[0].get();
			if (data.Param2 == 0) temp[1] = res[1].get();
			if (data.Param3 == 0) temp[2] = res[2].get();

			if (m_bEmpyRun)
			{
				//m_pflexComm->PutDutResult(data.Param0,
				//	temp[0].data.erroCode, temp[1].data.erroCode, temp[2].data.erroCode,
				//	temp[0].data.x, temp[0].data.y, temp[0].data.angle * 1000,
				//	temp[1].data.x, temp[1].data.y, temp[1].data.angle * 1000,
				//	temp[2].data.x, temp[2].data.y, temp[2].data.angle * 1000,
				//	0//本条命令的erroCode
				//);

				//emit postShowData(data.Param0, 0, 0, 0);
			}
			else
			{
				m_pflexComm->PutDutResult(GroupImgIndex + 1,
					temp[0].data.P0, temp[1].data.P0, temp[2].data.P0,
					temp[0].data.x, temp[0].data.y, Round_off(temp[0].data.R, 2) * 1000,
					temp[1].data.x, temp[1].data.y, Round_off(temp[1].data.R, 2) * 1000,
					temp[2].data.x, temp[2].data.y, Round_off(temp[2].data.R, 2) * 1000,
					0//本条命令的erroCode
				);

				//m_pflexComm->ReTakeDut(data, temp.data.x, temp.data.y, temp.data.angle * 1000, temp.data.erroCode, temp.strCode);
				//m_pflexComm->ReTakeDut(data, temp.data.x, temp.data.y, 0, temp.data.erroCode, temp.strCode);//屏蔽取料角度
				for (int i = 0; i < 3; ++i)
				{
					if (temp[i].data.P0 == 0)
						emit postShowData("放料" + QString::number(i + 4), "放料", temp[i].data.x, temp[i].data.y, Round_off(temp[i].data.R,2));
					else m_iTotalPositingFail++;
				}
			}
			auto end = GetmtfInstance()->GetTimeNow();
			double durationTime = GetmtfInstance()->durationTime(end, start, TimeType::second);
			LOG_DEBUG(glogger, MultUtf82Mult2("放料第") << 2 << MultUtf82Mult2("组吸嘴图像处理总耗时：") << durationTime);
		};
		gthpool->AddTask(fun);
	}
	else if (data.Param0 == 5)//料盘放料前防呆拍照
	{
		auto fun = [=] {
			auto start = GetmtfInstance()->GetTimeNow();
			int GroupImgIndex = 4;
			if (GetImg(m_GroupImg[GroupImgIndex], CAM_NAME_2, 2, 0, GroupImgIndex)) m_pflexComm->RePhotograph(data, 0);
			else {
				m_pflexComm->RePhotograph(data, 1);
				return;
			}
			sptr<HObject> nozzleImg[3];
			nozzleImg[0] = mksptr<HObject>();
			nozzleImg[1] = mksptr<HObject>();
			nozzleImg[2] = mksptr<HObject>();
			sptr<HObject> Imgcode[3];
			Imgcode[0] = mksptr<HObject>();
			Imgcode[1] = mksptr<HObject>();
			Imgcode[2] = mksptr<HObject>();
			int nozzleIndex = -1;//0-2
			m_hdev->CropImage(*m_GroupImg[GroupImgIndex], *m_NnozzleImgRoi[9], *m_NnozzleImgRoi[10], *m_NnozzleImgRoi[11], *nozzleImg[0], *nozzleImg[1], *nozzleImg[2], *Imgcode[0], *Imgcode[1], *Imgcode[2], GroupImgIndex);
			_ImgRsult temp[3];
			std::future<_ImgRsult> res[3];
			for (int i = 0; i < 3; ++i)
			{
				int stdSlotIndex = -1;
				if (i == 0) {
					if (data.Param1 == 0) stdSlotIndex = data.Param7;
					else continue;
				}
				else if (i == 1) {
					if (data.Param2 == 0) stdSlotIndex = data.Param8;
					else continue;
				}
				else if (i == 2) {
					if (data.Param3 == 0) stdSlotIndex = data.Param9;
					else continue;
				}

				try
				{
					//res[i] = gthpool->AddTask(std::bind(&flexDlg::ImgProcess, this, data, nozzleIndex, stdSlotIndex, m_GroupImg[GroupImgIndex], nozzleImg[nozzleIndex], Imgcode[nozzleIndex]));
				}
				catch (...)
				{
					//LOG_DEBUG(glogger, MultUtf82Mult2("放料") << i + 4 << MultUtf82Mult2("号吸嘴Task任务@ImgProcess出错！"));
				}
			}
			if (data.Param1 == 0) temp[0] = res[0].get();
			if (data.Param2 == 0) temp[1] = res[1].get();
			if (data.Param3 == 0) temp[2] = res[2].get();

			m_pflexComm->DefenceResult(5, 0, 0);
			auto end = GetmtfInstance()->GetTimeNow();
			double durationTime = GetmtfInstance()->durationTime(end, start, TimeType::second);
			LOG_DEBUG(glogger,  MultUtf82Mult2("放料前防呆处理总耗时：") << durationTime);
		};
		//gthpool->AddTask(fun);
	}
	else if (data.Param0 == 6)//料盘放料后防呆拍照
	{
		auto fun = [=] {
			auto start = GetmtfInstance()->GetTimeNow();
			int GroupImgIndex = 5;
			if (GetImg(m_GroupImg[GroupImgIndex], CAM_NAME_2, 2, 1, GroupImgIndex)) m_pflexComm->RePhotograph(data, 0);
			else {
				m_pflexComm->RePhotograph(data, 1);
				return;
			}
			sptr<HObject> ImgSlot[24];
			for (int i=0;i< data.Param10;i++)
			{
				ImgSlot[i] = mksptr<HObject>();
			}




			_ImgRsult temp[24];
			std::future<_ImgRsult> res[24];


			for (int i = 0; i < 3; ++i)
			{
				int stdSlotIndex = -1;
				if (i == 0) {
					if (data.Param1 == 0) stdSlotIndex = data.Param7;
					else continue;
				}
				else if (i == 1) {
					if (data.Param2 == 0) stdSlotIndex = data.Param8;
					else continue;
				}
				else if (i == 2) {
					if (data.Param3 == 0) stdSlotIndex = data.Param9;
					else continue;
				}

				try
				{
					//res[i] = gthpool->AddTask(std::bind(&flexDlg::ImgProcess, this, data, nozzleIndex, stdSlotIndex, m_GroupImg[GroupImgIndex], nozzleImg[nozzleIndex], Imgcode[nozzleIndex]));
				}
				catch (...)
				{
					//LOG_DEBUG(glogger, MultUtf82Mult2("放料") << i + 4 << MultUtf82Mult2("号吸嘴Task任务@ImgProcess出错！"));
				}
			}
			if (data.Param1 == 0) temp[0] = res[0].get();
			if (data.Param2 == 0) temp[1] = res[1].get();
			if (data.Param3 == 0) temp[2] = res[2].get();

			m_pflexComm->DefenceResult(6, 0, 0);
			auto end = GetmtfInstance()->GetTimeNow();
			double durationTime = GetmtfInstance()->durationTime(end, start, TimeType::second);
			LOG_DEBUG(glogger, MultUtf82Mult2("放料后防呆处理总耗时：") << durationTime);
		};
		gthpool->AddTask(fun);
	}
}

_ImgRsult flexDlg::ImgProcess(StFixedData data, int nozzleIndex, int StdSlotIndex, sptr<HObject> GroupImg, sptr<HObject> ImageNozzle, sptr<HObject> ImageCode)
{
	//========================================初始化逻辑参数========================================================
	QString CurrentCamName;
	int ALLNozzleIndex = -1;//所有吸嘴编号：0-11
	int CameraIndex = -1;
	int MatIndex = -1;//9Point File
	int RotateCenterIndex = -1;
	int MetrologyIndex = -1;
	int ImgProcessType = -1;
	int DispWindNo = -1;
	int orientation = 0;
	int GroupIndex = -1;
	bool bCheckModel = data.ChannelId;//点检模式标志位
	//int StdSlotIndex = 0;//24放料标准位置索引

	QDateTime DateTime = QDateTime::currentDateTime();
	QString strProcessDateTime = DateTime.toString("yyyy-MM-dd_hh_mm_ss");
	QString strProcessDate = DateTime.date().toString("yyyy-MM-dd");
	QString strProcessTime = DateTime.time().toString("hh_mm_ss");
	QString strProcessTimeDot = DateTime.time().toString("hh:mm:ss");




	if (data.Param0 == 1) //取料第一组：0-2吸头
	{
		GroupIndex = 0;
		ALLNozzleIndex = nozzleIndex;
		orientation = 0;
		CameraIndex = 0;
		MatIndex = 0;
		MetrologyIndex = ALLNozzleIndex;
		RotateCenterIndex = ALLNozzleIndex;
		ImgProcessType = 0;
		DispWindNo = ALLNozzleIndex;
		CurrentCamName = CAM_NAME_0;
	}
	else if (data.Param0 == 2)//取料第二组：3-5吸头
	{
		GroupIndex = 1;
		ALLNozzleIndex = nozzleIndex + 3;		
		orientation = 0;
		CameraIndex = 0;
		MatIndex = 0;
		MetrologyIndex = ALLNozzleIndex;
		RotateCenterIndex = ALLNozzleIndex;
		ImgProcessType = 0;
		DispWindNo = nozzleIndex + 3;
		CurrentCamName = CAM_NAME_0;
	}
	else if (data.Param0 == 3)//放料第一组：0-2吸头
	{
		GroupIndex =2;
		ALLNozzleIndex = nozzleIndex + 6;
		orientation = 0;
		CameraIndex = 1;
		MatIndex = 1;
		MetrologyIndex = ALLNozzleIndex;
		RotateCenterIndex = ALLNozzleIndex;
		ImgProcessType = 1;
		DispWindNo = nozzleIndex;
		CurrentCamName = CAM_NAME_1;
	}
	else if (data.Param0 == 4)//放料第二组：3-5吸头
	{
		GroupIndex = 3;
		ALLNozzleIndex = nozzleIndex + 9;
		orientation = 0;
		CameraIndex = 1;
		MatIndex = 1;
		MetrologyIndex = ALLNozzleIndex;
		RotateCenterIndex = ALLNozzleIndex;
		ImgProcessType = 1;
		DispWindNo = nozzleIndex + 3;
		CurrentCamName = CAM_NAME_1;
	}

	//================================================================================================
	DataInfo imgPointResult;
	_ImgRsult imgResult;
	int LocationFailCount = 0;


	HTuple iResult, findRow, findColumn, findAngle, findScale, findScore, OffsetX, OffsetY, OffsetR;
	HTuple StandOffsetLoadRobotX, StandOffsetLoadRobotY;
	int imgProcessResult = 0;
	HObject Image2DCode;

	if ((0 <= ALLNozzleIndex) && (ALLNozzleIndex <= 5))
	{
		StandOffsetLoadRobotX = m_StandOffsetLoadRobot.at(ALLNozzleIndex).x;
		StandOffsetLoadRobotY = m_StandOffsetLoadRobot.at(ALLNozzleIndex).y;
	}
	else
	{
		StandOffsetLoadRobotX = 0;
		StandOffsetLoadRobotY = 0;
	}


	bool bGetImgResultError = false;
	QString text, strPhotoID, NoErrorText;
	if (ALLNozzleIndex <= 5)
	{
		strPhotoID = "取料嘴" + QString::number(ALLNozzleIndex + 1) + ":";
	}
	else if (6 <= ALLNozzleIndex && ALLNozzleIndex <= 11)
	{
		strPhotoID = "放料嘴" + QString::number(ALLNozzleIndex - 5) + ":";
	}


	double 	 TrayOffsetX = 0, TrayOffsetY = 0, TrayOffsetR = 0;
	if (!m_bShieldTrayLocation)
	{
		TrayOffsetX = m_TrayOffsetX;
		TrayOffsetY = m_TrayOffsetY;
		TrayOffsetR = m_TrayOffsetR;
	}

	auto start1 = GetmtfInstance()->GetTimeNow();

	try {

		if (m_bEmpyRun && !m_bEmpyRunWithSimImg)
		{
			imgProcessResult = (int)ImgProResult::emptyRun;//空跑模式运行中
			//bGetImgResultError = true;
		}
		else
		{
			HRegion InRegion;
			GenEmptyRegion(&InRegion);
			m_hdev->GetImgProResult(*ImageNozzle, InRegion,
				*m_ResultRegion[ALLNozzleIndex], *m_Cross[ALLNozzleIndex], *m_ModelContourXld[ALLNozzleIndex], Image2DCode,
				*m_SearchContourXld[ALLNozzleIndex], *m_PointCrossXld[ALLNozzleIndex],
				m_ModelID, m_MetrologyHandle[MetrologyIndex], m_Mat[MatIndex], m_ControlPara.at(MatIndex).P2, ImgProcessType,
				StandOffsetLoadRobotX, StandOffsetLoadRobotY,
				m_StandImagePos.at(StdSlotIndex).x, m_StandImagePos.at(StdSlotIndex).y, m_StandImagePos.at(StdSlotIndex).R,
				m_RotateCenterImg.at(RotateCenterIndex).x, m_RotateCenterImg.at(RotateCenterIndex).y,
				m_ManualBCRobot.at(StdSlotIndex).x, m_ManualBCRobot.at(StdSlotIndex).y, m_ManualBCRobot.at(StdSlotIndex).R,
				TrayOffsetX, TrayOffsetY, TrayOffsetR, orientation,
				&iResult, &findRow, &findColumn, &findAngle, &findScale, &findScore, &OffsetX, &OffsetY, &OffsetR);

			imgProcessResult = iResult.I();//-1,-2,-3,-4
			if (5 < ALLNozzleIndex)//放料
			{
				if ((OffsetX.Length() == 0) || (OffsetY.Length() == 0) || (OffsetR.Length() == 0))
				{
					bGetImgResultError = true;//为空必定是出错
				}
				else
				{
					imgPointResult.x = OffsetX.D(), imgPointResult.y = OffsetY.D(), imgPointResult.R = OffsetR.D();
					//imgPointResult.angle = EqualAngle(imgPointResult.angle);
					imgPointResult.R = imgPointResult.R;

					if (m_RepeatTest)
					{
						auto fun = [=] {
							//lockup(m_WriteRepeatTestCsvMutex);
							QString num = QString::number(ALLNozzleIndex - 5);
							QString FolderPath = m_RepeatTestDataFolderPath + "/" + strProcessDate + "/验证数据";
							if (!GetmtfInstance()->isFolderExist(FolderPath))
							{
								GetmtfInstance()->CreateExteriorFolder(FolderPath);
							}
							QString filePath = FolderPath + "/下相机" + num + "号吸嘴验证数据.csv";

							if (!GetmtfInstance()->isFileExist(filePath))
							{
								WriteRepeatTestCsvHeader(filePath);
							}
							WriteRepeatTestCsvData(strProcessTimeDot, ALLNozzleIndex - 5, findRow.D(), findColumn.D(), findAngle.D(),
								OffsetX.D() / 1000, OffsetY.D() / 1000, EqualAngle(OffsetR.D()),
								filePath);
							if ((!m_bSimulate || m_bSimulateSavePic) && m_bSaveOkPic)
							{
								auto SaveImagefun = [=] {
									QString num = QString::number(ALLNozzleIndex - 5);
									QString FolderPath = m_RepeatTestDataFolderPath + "/" + strProcessDate + "/验证图像";
									if (!GetmtfInstance()->isFolderExist(FolderPath))
									{
										GetmtfInstance()->CreateExteriorFolder(FolderPath);
									}
									QString folderPathPic = FolderPath + "/下相机" + num + "号吸嘴图像";
									if (m_bSaveOriginalPicture)
									{
										Imgtfc::SaveImage(GroupImg, strProcessTime, folderPathPic);
									}
									else
									{
										Imgtfc::SaveImageCompression(GroupImg, strProcessTime, folderPathPic);
									}
								};
								gthpool->AddTask(SaveImagefun);
							}
						};
						gthpool->AddTask(fun);
					}
					else
					{
						auto fun = [=] {
							//lockup(m_WriteRectifyCsvMutex);
							QString num = QString::number(ALLNozzleIndex - 5);
							QString FolderPath = m_RectificationDataFolderPath + "/" + strProcessDate;
							if (!GetmtfInstance()->isFolderExist(FolderPath))
							{
								GetmtfInstance()->CreateExteriorFolder(FolderPath);
							}
							QString filePath = FolderPath + "/下相机" + num + "号吸嘴纠偏数据.csv";
							if (!GetmtfInstance()->isFileExist(filePath))
							{
								WritePutDutDataCsvHeader(filePath);
							}
							WritePutDutDataCsvData(strProcessTimeDot, ALLNozzleIndex - 5, m_strCode[ALLNozzleIndex - 6], findRow.D(), findColumn.D(), findAngle.D(),
								OffsetX.D() / 1000, OffsetY.D() / 1000, EqualAngle(OffsetR.D()),
								filePath);
						};
						gthpool->AddTask(fun);

						if ((!m_bSimulate || m_bSimulateSavePic) && m_bSaveOkPic)
						{
							auto SaveImagefun = [=] {
								QString num = QString::number(ALLNozzleIndex - 5);
								QString folderPath = m_FlexPictureFolderPath + "/" + strProcessDate + "/下相机" + num + "号吸嘴图像";
								if (m_bSaveOriginalPicture)
								{
									//Imgtfc::SaveImage(*GroupImg, m_strCode[ALLNozzleIndex - 6], folderPath);
									Imgtfc::SaveImage(GroupImg, strProcessTime + "-" + num + "-" + m_strCode[ALLNozzleIndex - 6], folderPath);
								}
								else
								{
									Imgtfc::SaveImageCompression(GroupImg, strProcessTime + "-" + num + "-" + m_strCode[ALLNozzleIndex - 6], folderPath);
								}
							};
							gthpool->AddTask(SaveImagefun);
						}
					}
				}
			}
		}
	}
	catch (...)
	{
		imgProcessResult = (int)ImgProResult::ImgProFuncError;//图像处理函数报错
		bGetImgResultError = true;
	}

	auto end1 = GetmtfInstance()->GetTimeNow();
	double durationTime1 = GetmtfInstance()->durationTime(end1, start1, TimeType::second);
	LOG_DEBUG(glogger, MultUtf82Mult2("第") << ALLNozzleIndex + 1 << MultUtf82Mult2("号吸嘴GetImgProResult耗时：") << durationTime1);


	if (imgProcessResult == (int)ImgProResult::NoError)
	{
		text = strPhotoID + "(" + QString::number(Round_off(imgPointResult.x / 1000, 3)) + "," + QString::number(Round_off(imgPointResult.y / 1000, 3)) + "," + QString::number(Round_off(imgPointResult.R, 3)) + ")";
	}
	else
	{
		if (imgProcessResult == (int)ImgProResult::ReDataEmpty) {
			text = strPhotoID + "无产品，定位点查找失败返回数据为空!";
			if ((!m_bSimulate || m_bSimulateSavePic) && m_bSaveNGPic)
			{
				auto SaveNGPicFun = [=] {
					QString num;
					QString picName;
					if (GroupIndex >= 2)
					{
						num = QString::number(ALLNozzleIndex - 5);
						picName = strProcessTime + "-" + num + "-" + m_strCode[ALLNozzleIndex - 6];
					}
					else
					{
						num = QString::number(ALLNozzleIndex + 1);
						picName = strProcessTime + "-" + num;
					}

					if (m_bSaveOriginalPicture)
					{
						Imgtfc::SaveImage(ImageNozzle, CameraIndex, strProcessDate + "/无产品定位点查找失败返回数据为空", Icg::getAppConfigInfo().SaveDetectFailPicPath, "Camera", picName);
					}
					else {
						Imgtfc::SaveImageCompression(ImageNozzle, CameraIndex, strProcessDate + "/无产品定位点查找失败返回数据为空", Icg::getAppConfigInfo().SaveDetectFailPicPath, "Camera", picName);
					}

				};
				gthpool->AddTask(SaveNGPicFun);
			}
		}
		else if (imgProcessResult == (int)ImgProResult::ModelMatchError) {
			text = strPhotoID + "无产品，定位图像处理出错返回数据为空！";
			if ((!m_bSimulate || m_bSimulateSavePic) && m_bSaveNGPic)
			{
				auto SaveNGPicFun = [=] {
					QString num;
					QString picName;
					if (GroupIndex >= 2)
					{
						num = QString::number(ALLNozzleIndex - 5);
						picName = strProcessTime + "-" + num + "-" + m_strCode[ALLNozzleIndex - 6];
					}
					else
					{
						num = QString::number(ALLNozzleIndex + 1);
						picName = strProcessTime + "-" + num;
					}
					if (m_bSaveOriginalPicture)
					{
						Imgtfc::SaveImage(ImageNozzle, CameraIndex, strProcessDate + "/无产品定位图像处理出错返回数据为空", Icg::getAppConfigInfo().SaveDetectFailPicPath, "Camera", picName);
					}
					else
					{
						Imgtfc::SaveImageCompression(ImageNozzle, CameraIndex, strProcessDate + "/无产品定位图像处理出错返回数据为空", Icg::getAppConfigInfo().SaveDetectFailPicPath, "Camera", picName);
					}

				};
				gthpool->AddTask(SaveNGPicFun);
			}
		}
		else if (imgProcessResult == (int)ImgProResult::LoactionError) {
			text = strPhotoID + "有产品，定位失败！";
			if ((!m_bSimulate || m_bSimulateSavePic) && m_bSaveNGPic)
			{
				auto SaveNGPicFun = [=] {
					QString num;
					QString picName;
					if (GroupIndex >= 2)
					{
						num = QString::number(ALLNozzleIndex - 5);
						picName = strProcessTime + "-" + num + "-" + m_strCode[ALLNozzleIndex - 6];
					}
					else
					{
						num = QString::number(ALLNozzleIndex + 1);
						picName = strProcessTime + "-" + num;
					}
					if (m_bSaveOriginalPicture)
					{
						Imgtfc::SaveImage(ImageNozzle, CameraIndex, strProcessDate + "/有产品定位失败", Icg::getAppConfigInfo().SaveDetectFailPicPath, "Camera", picName);
					}
					else {
						Imgtfc::SaveImageCompression(ImageNozzle, CameraIndex, strProcessDate + "/有产品定位失败", Icg::getAppConfigInfo().SaveDetectFailPicPath, "Camera", picName);
					}
				};
				gthpool->AddTask(SaveNGPicFun);
			}
		}
		else if (imgProcessResult == (int)ImgProResult::ProductNG) {
			text = strPhotoID + "产品外观NG";
			if ((!m_bSimulate || m_bSimulateSavePic) && m_bSaveNGPic)
			{
				auto SaveNGPicFun = [=] {
					QString num;
					QString picName;
					if (GroupIndex >= 2)
					{
						num = QString::number(ALLNozzleIndex - 5);
						picName = strProcessTime + "-" + num + "-" + m_strCode[ALLNozzleIndex - 6];
					}
					else
					{
						num = QString::number(ALLNozzleIndex + 1);
						picName = strProcessTime + "-" + num;
					}
					if (m_bSaveOriginalPicture)
					{
						Imgtfc::SaveImage(ImageNozzle, CameraIndex, strProcessDate + "/产品外观NG", Icg::getAppConfigInfo().SaveDetectFailPicPath, "Camera", picName);
					}
					else
					{
						Imgtfc::SaveImageCompression(ImageNozzle, CameraIndex, strProcessDate + "/产品外观NG", Icg::getAppConfigInfo().SaveDetectFailPicPath, "Camera", picName);
					}

				};
				gthpool->AddTask(SaveNGPicFun);
			}
		}
		else if (imgProcessResult == (int)ImgProResult::ProductImgError) {
			text = strPhotoID + "产品外观检测出错";
			if ((!m_bSimulate || m_bSimulateSavePic) && m_bSaveNGPic)
			{
				auto SaveNGPicFun = [=] {
					QString num;
					QString picName;
					if (GroupIndex >= 2)
					{
						num = QString::number(ALLNozzleIndex - 5);
						picName = strProcessTime + "-" + num + "-" + m_strCode[ALLNozzleIndex - 6];
					}
					else
					{
						num = QString::number(ALLNozzleIndex + 1);
						picName = strProcessTime + "-" + num;
					}
					if (m_bSaveOriginalPicture)
					{
						Imgtfc::SaveImage(ImageNozzle, CameraIndex, strProcessDate + "/产品外观检测出错", Icg::getAppConfigInfo().SaveDetectFailPicPath, "Camera", picName);
					}
					else
					{
						Imgtfc::SaveImageCompression(ImageNozzle, CameraIndex, strProcessDate + "/产品外观检测出错", Icg::getAppConfigInfo().SaveDetectFailPicPath, "Camera", picName);
					}

				};
				gthpool->AddTask(SaveNGPicFun);
			}
		}
		else if (imgProcessResult == (int)ImgProResult::emptyRun)  text = strPhotoID + "空跑模式运行中...";
		else if (imgProcessResult == (int)ImgProResult::ImgProFuncError) {
			text = strPhotoID + "图像处理函数报错！";
			if ((!m_bSimulate || m_bSimulateSavePic) && m_bSaveNGPic)
			{
				auto SaveNGPicFun = [=] {
					QString num;
					QString picName;
					if (GroupIndex >= 2)
					{
						num = QString::number(ALLNozzleIndex - 5);
						picName = strProcessTime + "-" + num + "-" + m_strCode[ALLNozzleIndex - 6];
					}
					else
					{
						num = QString::number(ALLNozzleIndex + 1);
						picName = strProcessTime + "-" + num;
					}

					if (m_bSaveOriginalPicture)
					{
						Imgtfc::SaveImage(ImageNozzle, CameraIndex, strProcessDate + "/图像处理函数报错", Icg::getAppConfigInfo().SaveDetectFailPicPath, "Camera", picName);
					}
					else
					{
						Imgtfc::SaveImageCompression(ImageNozzle, CameraIndex, strProcessDate + "/图像处理函数报错", Icg::getAppConfigInfo().SaveDetectFailPicPath, "Camera", picName);
					}

				};
				gthpool->AddTask(SaveNGPicFun);
			}
		}

		if (imgProcessResult == (int)ImgProResult::ProductNG || imgProcessResult == (int)ImgProResult::ProductImgError)
		{
			if (m_bShieldAppearance) //屏蔽外观检测
			{
				imgProcessResult = (int)ImgProResult::NoError;
				text = strPhotoID + "(" + QString::number(Round_off(imgPointResult.x / 1000, 3)) + "," + QString::number(Round_off(imgPointResult.y / 1000, 3)) + "," + QString::number(Round_off(imgPointResult.R, 3)) + ")";
			}
		}
	}

	if (imgProcessResult != (int)ImgProResult::NoError)//图像处理错误，错误分类
	{
		m_pwnd[DispWindNo]->SetDispStyle("margin", "red");
		DlgDispImg(m_pwnd[DispWindNo], "", GroupImg, m_NnozzleImgRoi[ALLNozzleIndex], m_ResultRegion[ALLNozzleIndex], m_Cross[ALLNozzleIndex], m_ModelContourXld[ALLNozzleIndex], m_SearchContourXld[ALLNozzleIndex], m_PointCrossXld[ALLNozzleIndex]);
		Imgtfc::dispText(m_pwnd[DispWindNo]->m_hHalconID, (int)TL::Row1, 200, text, "red");
		if (imgProcessResult == (int)ImgProResult::LoactionError || imgProcessResult == (int)ImgProResult::ImgProFuncError)
		{
			imgPointResult.P0 = (int)ErrorCode::LocationFail;//有产品，定位失败
			if (LocationFailCount < 2)
			{
				LocationFailCount++;
				//goto labe_1;
			}
			imgResult.data = imgPointResult;
			return imgResult;
		}
		if (imgProcessResult == (int)ImgProResult::ReDataEmpty || imgProcessResult == (int)ImgProResult::ModelMatchError)
		{
			imgPointResult.P0 = (int)ErrorCode::NoProduct;
			imgResult.data = imgPointResult;
			return imgResult;
		}
		if (!m_bShieldAppearance && (ALLNozzleIndex <= 5) && (imgProcessResult == (int)ImgProResult::ProductNG || imgProcessResult == (int)ImgProResult::ProductImgError))
		{
			imgPointResult.P0 = (int)ErrorCode::ProductNG;
		}

		if (!m_bShieldAppearance || 5 < ALLNozzleIndex)//不屏蔽，NG返回，5 <ALLNozzleIndex即其它错误在次返回
		{
			imgResult.data = imgPointResult;
			return imgResult;
		}
		else if (m_bShieldAppearance && (ALLNozzleIndex <= 5))//屏蔽
		{
			imgProcessResult = (int)ImgProResult::NoError;
		}
	}

	//=============================扫码===================================================================

	int _2DCodeResult = 0;
	sptr<HObject> SymbolXLDs = mksptr<HObject>();
	HTuple  res, Code;
	QString strCode;
	QString strCodeText;
	QString MesReMessage;

	if (CameraIndex == 0 && ALLNozzleIndex <= 5)//获取取料扫码图
	{
		if (m_bEmpyRun && !m_bEmpyRunWithSimImg)
		{
			_2DCodeResult = (int)CodeResult::emptyRun;//空跑模式运行中
		}
		else
		{
			auto startReadCode = GetmtfInstance()->GetTimeNow();
			try
			{
				HRegion Region;
				GenEmptyRegion(&Region);
				m_hdev->Get2DCode(*ImageCode,Region,Region,*SymbolXLDs, m_2DCodeModel,0, &Code, &res);
				_2DCodeResult = res.I();
			}
			catch (...)
			{
				_2DCodeResult = (int)CodeResult::ImgProFuncError;//二维码图像处理函数报错
			}
			auto endReadCode = GetmtfInstance()->GetTimeNow();
			double durationTimeCode = GetmtfInstance()->durationTime(endReadCode, startReadCode, TimeType::second);
			LOG_DEBUG(glogger, MultUtf82Mult2("第") << ALLNozzleIndex + 1 << MultUtf82Mult2("号吸嘴Get2DCode耗时：") << durationTimeCode);

			if (_2DCodeResult == (int)CodeResult::NoError)
			{
				strCode = Code.ToString();
				strCode.replace("\"", "");
				strCodeText += "2DCode:" + strCode;
				m_strCode[ALLNozzleIndex] = strCode;
				QString strMesResult = "";
				if (m_pMesData->m_bConnectMes)
				{
					auto startCheckSn = GetmtfInstance()->GetTimeNow();
					int res = m_pMesData->CheckSn(strCode, MesReMessage);
					if (res != (int)CodeResult::NoError)
					{
						if (res == -1)
						{
							_2DCodeResult = (int)CodeResult::MesNG;
							strCodeText += "-->>Fail";
							strMesResult = "Fail";
						}
						else if (res == -4)
						{
							_2DCodeResult = (int)CodeResult::MesTimeOut;
							strCodeText += "-->>Mes返回超时！";
							strMesResult = "MesTimeOut";
						}
					}
					else
					{
						strCodeText += "-->>Pass";
						strMesResult = "Pass";
					}
					auto endCheckSn = GetmtfInstance()->GetTimeNow();
					double durationTimeCheckSn = GetmtfInstance()->durationTime(endCheckSn, startCheckSn, TimeType::second);
					LOG_DEBUG(glogger, MultUtf82Mult2("第") << ALLNozzleIndex + 1 << MultUtf82Mult2("号吸嘴CheckSn耗时：") << durationTimeCheckSn);
				}
				auto fun = [=] {
					auto start3 = GetmtfInstance()->GetTimeNow();
					lockup(m_Write2DCodeCsvMutex);
					QString FolderPath = m_SaveSnMesCheckCsvFolderPath;
					if (!GetmtfInstance()->isFolderExist(FolderPath))
					{
						GetmtfInstance()->CreateExteriorFolder(FolderPath);
					}
					QString filePath = FolderPath + "/" + strProcessDate + ".csv";
					if (!GetmtfInstance()->isFileExist(filePath))
					{
						Write2DCodeCsvHeader(filePath);
					}
					Write2DCodeCsvData(strProcessTimeDot, ALLNozzleIndex + 1, strCode, strMesResult, filePath);
					auto end3 = GetmtfInstance()->GetTimeNow();
					double durationTime3 = GetmtfInstance()->durationTime(end3, start3, TimeType::second);
					LOG_DEBUG(glogger, MultUtf82Mult2("第") << ALLNozzleIndex + 1 << MultUtf82Mult2("号吸嘴写csv耗时：") << durationTime3);
				};
				gthpool->AddTask(fun);

				if ((!m_bSimulate || m_bSimulateSavePic) && m_bSaveOkPic)
				{
					auto SaveImagefun = [=] {
						QString num = QString::number(ALLNozzleIndex + 1);
						QString folderPath = m_FlexPictureFolderPath + "/" + strProcessDate + "/上相机" + num + "号吸嘴图像";

						if (m_bSaveOriginalPicture)
						{
							Imgtfc::SaveImage(GroupImg, strProcessTime + "-" + num + "-" + m_strCode[ALLNozzleIndex], folderPath);
						}
						else
						{
							Imgtfc::SaveImageCompression(GroupImg, strProcessTime + "-" + num + "-" + m_strCode[ALLNozzleIndex], folderPath);
						}
					};
					gthpool->AddTask(SaveImagefun);
				}
				if (bCheckModel)
				{
					if (!m_CheckSnMap.contains(strCode))
					{
						_2DCodeResult = (int)CodeResult::NonCheckProduct;
						strCodeText += "-->>非点检料";
					}
				}

				if (!m_bOldEquipment && !m_vecFilterSN.empty() && (_2DCodeResult == (int)CodeResult::NoError))
				{
					bool isContainLocalSn = false;
					for (auto e : m_vecFilterSN)
					{
						if (strCode.contains(e))
						{
							isContainLocalSn = true;
							break;
						}
					}
					if (!isContainLocalSn)
					{
						_2DCodeResult = (int)CodeResult::MesNG;
						strCodeText += "-->>本地SN卡关失败！";
					}
				}
			}
			else if (_2DCodeResult == (int)CodeResult::ReadCodeFail)
			{
				if (!strCodeText.contains("2DCode"))
				{
					strCodeText += "2DCode: 二维码读取失败！";
				}
				if ((!m_bSimulate || m_bSimulateSavePic) && m_bSaveNGPic)
				{
					auto SaveNGPicFun = [=] {
						QString num;
						QString picName;
						if (GroupIndex <= 1)
						{
							num = QString::number(ALLNozzleIndex + 1);
							picName = strProcessTime + "-" + num;
						}
						if (m_bSaveOriginalPicture)
						{
							Imgtfc::SaveImage(ImageNozzle, CameraIndex, strProcessDate + "/二维码读取失败图片", Icg::getAppConfigInfo().SaveDetectFailPicPath, "Camera", picName);
						}
						else
						{
							Imgtfc::SaveImageCompression(ImageNozzle, CameraIndex, strProcessDate + "/二维码读取失败图片", Icg::getAppConfigInfo().SaveDetectFailPicPath, "Camera", picName);
						}

					};
					gthpool->AddTask(SaveNGPicFun);
				}

				auto fun = [=] {
					auto start3 = GetmtfInstance()->GetTimeNow();
					lockup(m_Write2DCodeCsvMutex);
					QString FolderPath = m_SaveSnMesCheckCsvFolderPath;
					if (!GetmtfInstance()->isFolderExist(FolderPath))
					{
						GetmtfInstance()->CreateExteriorFolder(FolderPath);
					}
					QString filePath = FolderPath + "/" + strProcessDate + ".csv";
					if (!GetmtfInstance()->isFileExist(filePath))
					{
						Write2DCodeCsvHeader(filePath);
					}
					Write2DCodeCsvData(strProcessTimeDot, ALLNozzleIndex + 1, "Failed", "", filePath);
					auto end3 = GetmtfInstance()->GetTimeNow();
					double durationTime3 = GetmtfInstance()->durationTime(end3, start3, TimeType::second);
					LOG_DEBUG(glogger, MultUtf82Mult2("第") << ALLNozzleIndex + 1 << MultUtf82Mult2("号吸嘴写csv耗时：") << durationTime3);
				};
				gthpool->AddTask(fun);
			}
			else if (_2DCodeResult == (int)CodeResult::MesNG)
			{


			}
			else if (_2DCodeResult == (int)CodeResult::emptyRun)
			{
				strCodeText += "2DCode: 空跑模式...";
			}
			else if (_2DCodeResult == (int)CodeResult::ImgProFuncError)
			{
				strCodeText += "2DCode: 二维码图像处理报错！";
				if ((!m_bSimulate || m_bSimulateSavePic) && m_bSaveNGPic)
				{
					auto SaveNGPicFun = [=] {
						QString num;
						QString picName;
						if (GroupIndex <= 1)
						{
							num = QString::number(ALLNozzleIndex + 1);
							picName = strProcessTime + "-" + num;
						}
						if (m_bSaveOriginalPicture)
						{
							Imgtfc::SaveImage(ImageNozzle, CameraIndex, strProcessDate + "/二维码图像处理报错图片", Icg::getAppConfigInfo().SaveDetectFailPicPath, "Camera", picName);
						}
						else
						{
							Imgtfc::SaveImage(ImageNozzle, CameraIndex, strProcessDate + "/二维码图像处理报错图片", Icg::getAppConfigInfo().SaveDetectFailPicPath, "Camera", picName);
						}

					};
					gthpool->AddTask(SaveNGPicFun);
				}
			}

			if (m_bShield2DCode && _2DCodeResult != (int)CodeResult::emptyRun)
			{
				_2DCodeResult = (int)CodeResult::NoError;
			}
		}
	}
	//================================================================================================

	if (imgProcessResult == (int)ImgProResult::NoError && _2DCodeResult == (int)CodeResult::NoError)
	{
		m_pwnd[DispWindNo]->SetDispStyle("margin", "green");
		imgPointResult.P0 = int(ErrorCode::NoError);
		DlgDispImg(m_pwnd[DispWindNo], "", GroupImg, m_NnozzleImgRoi[ALLNozzleIndex], m_ResultRegion[ALLNozzleIndex], m_Cross[ALLNozzleIndex], m_ModelContourXld[ALLNozzleIndex], SymbolXLDs, m_SearchContourXld[ALLNozzleIndex], m_PointCrossXld[ALLNozzleIndex]);
		Imgtfc::dispText(m_pwnd[DispWindNo]->m_hHalconID, (int)TL::Row1, 200, text, "green");
		if (ALLNozzleIndex <= 5) Imgtfc::dispText(m_pwnd[DispWindNo]->m_hHalconID, (int)TL::Row2, 200, strCodeText, "green");
		imgResult.data = imgPointResult;
		imgResult.strCode = strCode;
		return imgResult;
	}
	else if (imgProcessResult == (int)ImgProResult::NoError && (_2DCodeResult == (int)CodeResult::ReadCodeFail
		|| _2DCodeResult == (int)CodeResult::ImgProFuncError
		|| _2DCodeResult == (int)CodeResult::MesTimeOut))
	{
		m_pwnd[DispWindNo]->SetDispStyle("margin", "red");
		imgPointResult.P0 = int(ErrorCode::ReadCodeFail);
		DlgDispImg(m_pwnd[DispWindNo], "", m_GroupImg[GroupIndex], m_NnozzleImgRoi[ALLNozzleIndex], m_ResultRegion[ALLNozzleIndex], m_Cross[ALLNozzleIndex], m_ModelContourXld[ALLNozzleIndex], m_SearchContourXld[ALLNozzleIndex], m_PointCrossXld[ALLNozzleIndex]);
		Imgtfc::dispText(m_pwnd[DispWindNo]->m_hHalconID, (int)TL::Row1, 200, text, "red");
		if (ALLNozzleIndex <= 5) Imgtfc::dispText(m_pwnd[DispWindNo]->m_hHalconID, (int)TL::Row2, 200, strCodeText, "red");

		imgResult.data = imgPointResult;
		return imgResult;
	}
	else if (imgProcessResult == (int)ImgProResult::NoError && _2DCodeResult == (int)CodeResult::MesNG)
	{
		m_pwnd[DispWindNo]->SetDispStyle("margin", "red");
		imgPointResult.P0 = int(ErrorCode::MesNG);
		DlgDispImg(m_pwnd[DispWindNo], "", m_GroupImg[GroupIndex], m_NnozzleImgRoi[ALLNozzleIndex], m_ResultRegion[ALLNozzleIndex], m_Cross[ALLNozzleIndex], m_ModelContourXld[ALLNozzleIndex], m_SearchContourXld[ALLNozzleIndex], m_PointCrossXld[ALLNozzleIndex]);
		Imgtfc::dispText(m_pwnd[DispWindNo]->m_hHalconID, (int)TL::Row1, 200, text, "red");
		if (ALLNozzleIndex <= 5) {
			Imgtfc::dispText(m_pwnd[DispWindNo]->m_hHalconID, (int)TL::Row2, 200, strCodeText);
			Imgtfc::dispText(m_pwnd[DispWindNo]->m_hHalconID, (int)TL::Row3, 200, MesReMessage);
		}
		imgResult.data = imgPointResult;
		return imgResult;
	}
	else if (imgProcessResult == (int)ImgProResult::NoError && _2DCodeResult == (int)CodeResult::NonCheckProduct)
	{
		m_pwnd[DispWindNo]->SetDispStyle("margin", "red");
		imgPointResult.P0 = int(ErrorCode::NonCheckProduct);
		DlgDispImg(m_pwnd[DispWindNo], "", m_GroupImg[GroupIndex], m_NnozzleImgRoi[ALLNozzleIndex], m_ResultRegion[ALLNozzleIndex], m_Cross[ALLNozzleIndex], m_ModelContourXld[ALLNozzleIndex], m_SearchContourXld[ALLNozzleIndex], m_PointCrossXld[ALLNozzleIndex]);
		Imgtfc::dispText(m_pwnd[DispWindNo]->m_hHalconID, (int)TL::Row1, 200, text, "red");
		if (ALLNozzleIndex <= 5) {
			Imgtfc::dispText(m_pwnd[DispWindNo]->m_hHalconID, (int)TL::Row2, 200, strCodeText);
		}
		imgResult.data = imgPointResult;
		return imgResult;
	}
	else if (imgProcessResult == (int)ImgProResult::emptyRun || _2DCodeResult == (int)CodeResult::emptyRun)
	{
		m_pwnd[DispWindNo]->SetDispStyle("margin", "red");
		imgPointResult.P0 = int(ErrorCode::EmptyRun);
		DlgDispImg(m_pwnd[DispWindNo], "5", m_GroupImg[GroupIndex], m_NnozzleImgRoi[ALLNozzleIndex], m_ResultRegion[ALLNozzleIndex], m_Cross[ALLNozzleIndex], m_ModelContourXld[ALLNozzleIndex], SymbolXLDs, m_SearchContourXld[ALLNozzleIndex], m_PointCrossXld[ALLNozzleIndex]);
		Imgtfc::dispText(m_pwnd[DispWindNo]->m_hHalconID, (int)TL::Row1, 200, text);
		if (ALLNozzleIndex <= 5) Imgtfc::dispText(m_pwnd[DispWindNo]->m_hHalconID, (int)TL::Row2, 200, strCodeText);
		imgResult.data = imgPointResult;
		return imgResult;
	}
	imgResult.data = imgPointResult;
	return imgResult;
}

//收到 客户端回复服务端请求，触发信号：======================================================================================================================
void flexDlg::OnRecvReHeartBeat(StFixedData data, bool bCheckTimeOut /*= false*/)
{
	if (bCheckTimeOut)	m_pflexDispDlg->LightStatus(m_pflexDispDlg->m_pBtnStatePLc, 0);
	else m_pflexDispDlg->LightStatus(m_pflexDispDlg->m_pBtnStatePLc, 1);
}

void flexDlg::OnRecvReGetAbsPos(StFixedData data, bool bCheckTimeOut /*= false*/)
{
	m_GetRobotPos.x = data.Param4;
	m_GetRobotPos.y = data.Param5;
	m_GetRobotPos.R = data.Param6;
	m_isGetRobotPos = true;
}

void flexDlg::OnRecvReRelativeMove(StFixedData data, bool bCheckTimeOut /*= false*/)
{
	MessageBoxTip("机械手移动到位！");
}

void flexDlg::OnRecvReTakeDutResult(StFixedData data, bool bCheckTimeOut /*= false*/)
{

	//LOG_INFO(glogger, MultUtf82Mult2("收到取料数据回复！"));
}

void flexDlg::OnRecvRePutDutResult(StFixedData data, bool bCheckTimeOut /*= false*/)
{

	//LOG_INFO(glogger, MultUtf82Mult2("收到放料数据回复！"));
}

void flexDlg::OnRecvReDefenceResult(StFixedData data, bool bCheckTimeOut)
{
	LOG_INFO(glogger, MultUtf82Mult2("收到防呆结果回复！"));

}


//==============================================================================================================================================
void flexDlg::DefaultPathConvert()
{
	bool ret = GetmtfInstance()->DefaultPathConvert("flex/File", m_PlcCmdPath);

	for (int i = 0; i < m_ModelFilefullPath.size(); i++)
	{
		QString temp = toqstr(m_ModelFilefullPath.at(i));
		GetmtfInstance()->DefaultPathConvert("flex/File", temp);
		m_ModelFilefullPath.at(i) = temp.tostr();
	}

	for (int i = 0; i < m_MatFilefullPath.size(); i++)
	{
		QString temp = toqstr(m_MatFilefullPath.at(i));
		GetmtfInstance()->DefaultPathConvert("flex/File", temp);
		m_MatFilefullPath.at(i) = temp.tostr();
	}
}

void flexDlg::LoadCalibFile()
{
	m_ModelFilefullPath.clear();
	m_MatFilefullPath.clear();
	for (int i = 0; i < 12; i++)//取料6个，放料6个共12个
	{
		QString path = "DataFile/Panel/File/Metrology";
		QString file = "flexMetrology.dat";
		QString pathFile = GetmtfInstance()->CreateInnerFile(0, path, file);
		m_ModelFilefullPath.push_back(pathFile.tostr());
	}

	for (int i = 0; i < 2; i++)//取料1个，放料1个，共2个
	{	
		QString path = "DataFile/Panel/File/Calibrate/9PointMatrix/9PointMatrix_DownCamera";
		QString file = "9PointMatrix_DownCamera.mat";
		QString pathFile = GetmtfInstance()->CreateInnerFile(0, path, file);
		m_MatFilefullPath.push_back(pathFile.tostr());
	}

	try
	{
		for (int i = 0; i < m_ModelFilefullPath.size(); i++)
		{
			QString temp = toqstr(m_ModelFilefullPath.at(i));
			HTuple path = temp.toLocal8Bit().data();//已转StdString
			ReadMetrologyModel(path, &m_MetrologyHandle[i]);
		}
	}
	catch (...)
	{
		LOG_DEBUG(glogger, MultUtf82Mult2("加载测量文件出错！"));
		MessageBoxTip("加载测量文件出错！");
	}

	try
	{
		for (int i = 0; i < m_MatFilefullPath.size(); i++)
		{
			HTuple hv_FileHandle, hv_SerializedItemHandle;
			QString temp = toqstr(m_MatFilefullPath.at(i));
			HalconCpp::SetHcppInterfaceStringEncodingIsUtf8(false);//
			HTuple path = temp.toLocal8Bit().data();//已转StdString
			OpenFile(path, "input_binary", &hv_FileHandle);
			FreadSerializedItem(hv_FileHandle, &hv_SerializedItemHandle);
			DeserializeHomMat2d(hv_SerializedItemHandle, &m_Mat[i]);
			::CloseFile(hv_FileHandle);
		}
	}
	catch (HDevEngineException e)
	{
		std::string text = e.Message();
		LOG_DEBUG(glogger, text.data());
		LOG_DEBUG(glogger, MultUtf82Mult2("加载标定文件出错！"));
		MessageBoxTip("加载标定文件出错:" + toqstr(text));
	}

	try
	{
		HalconCpp::SetHcppInterfaceStringEncodingIsUtf8(false);//
		for (int i = 0; i < 12; i++)
		{
			QString path = "DataFile/Panel/File/ROI";
			QString file = "Roi_"+QString::number(i+1)+".hobj";
			QString pathFile = GetmtfInstance()->CreateInnerFile(0, path, file);
			HTuple hvPath = pathFile.toLocal8Bit().data();
			m_NnozzleImgRoi[i] = std::make_shared<HObject>();
			ReadObject(m_NnozzleImgRoi[i].get(), hvPath);//ReadObject
		}
	}
	catch (...)
	{
		LOG_DEBUG(glogger, MultUtf82Mult2("加载ROI出错！"));
		MessageBoxTip("加载ROI出错！");
	}

	try
	{
		 QString path = "DataFile/Panel/File/2DCodeModel";
		 QString file = "flex.dcm";
		 QString pathFile = GetmtfInstance()->CreateInnerFile(0, path, file);
		 HTuple path2 = pathFile.toLocal8Bit().data();
		 ReadDataCode2dModel(path2, &m_2DCodeModel);
	}
	catch (...)
	{
		LOG_DEBUG(glogger, MultUtf82Mult2("加载二维码句柄出错！"));
		MessageBoxTip("加载二维码句柄出错！");
	}

	try
	{
		QString path = "DataFile/Panel/File/Region";
		QString file = "stdRegion_1.hobj";
		QString pathFile = GetmtfInstance()->CreateInnerFile(0, path, file);
		HTuple hvPath = pathFile.toLocal8Bit().data();
		HalconCpp::SetHcppInterfaceStringEncodingIsUtf8(false);//
		ReadRegion(&m_StdRegion[0], hvPath);

		file = "stdRegion_2.hobj";
	    pathFile = GetmtfInstance()->CreateInnerFile(0, path, file);
		hvPath = pathFile.toLocal8Bit().data();
		ReadRegion(&m_StdRegion[1], hvPath);
	}
	catch (...)
	{
		//std::string text = e.Message();
		//LOG_DEBUG(glogger, text.data());
		LOG_DEBUG(glogger, MultUtf82Mult2("加载标准Region出错！"));
		MessageBoxTip("加载标准Region出错!" );
	}

	try
	{
		QString path = "DataFile/Panel/File/Model/DownCamera";
		QString file = "DownCamera.shm";
		QString pathFile = GetmtfInstance()->CreateInnerFile(0, path, file);
		HTuple path2 = pathFile.toLocal8Bit().data();
		ReadShapeModel(path2, &m_ModelID);
	}
	catch (...)
	{
		LOG_DEBUG(glogger, MultUtf82Mult2("下相机模板句柄加载出错！"));
		MessageBoxTip("下相机模板句柄加载出错！");
	}
}

void flexDlg::DispVersion_cb(QStatusBar* pStatusBar, QLabel& label)
{
	label.setStyleSheet(" color: white;  font: 12pt '楷书'; ");
	pStatusBar->setStyleSheet("background: brown; ");
	pStatusBar->addPermanentWidget(&label);
	label.setText(m_Version);
}

void flexDlg::CameraLinkState_cb(int camNum, bool isLinked)
{
	m_pThis->InitCameraPara();
	LOG_TRACE(GetmtpLogger(), "============CameraLinkState_cb========="<< camNum);
	static bool bRegister1=false, bRegister2=false;
	if (isLinked && (!bRegister1|| !bRegister2))
	{
      Icg::getNameCameraMap()["Camera"+QString::number(camNum)]->RegConnectStateFun(ConnectStateFun_cb, m_pThis);
	  if (camNum == 1) bRegister1 = true;
	  else if (camNum == 2) bRegister2 = true;
	}
	switch (camNum)
	{
	case 1:
		if (isLinked) 	m_pflexDispDlg->LightStatus(m_pflexDispDlg->m_pBtnStateCam_1, 1);
		else m_pflexDispDlg->LightStatus(m_pflexDispDlg->m_pBtnStateCam_1, 0);
		break;
	case 2:
		if (isLinked) 	m_pflexDispDlg->LightStatus(m_pflexDispDlg->m_pBtnStateCam_2, 1);
		else m_pflexDispDlg->LightStatus(m_pflexDispDlg->m_pBtnStateCam_2, 0);
		break;
	case 3:
		if (isLinked) 	m_pflexDispDlg->LightStatus(m_pflexDispDlg->m_pBtnStateCam_3, 1);
		else m_pflexDispDlg->LightStatus(m_pflexDispDlg->m_pBtnStateCam_3, 0);
		break;
	case 4:
		//if (isLinked) 	m_pflexDispDlg->LightStatus(m_pflexDispDlg->m_pBtnStateCam_4, 1);
		//else m_pflexDispDlg->LightStatus(m_pflexDispDlg->m_pBtnStateCam_4, 0);
		break;
	default:
		break;
	}
}

void flexDlg::OnDataInteraction_cb()
{
	if (g_pMesDlg != nullptr)
	{
		g_pMesDlg->show();
	}
}

void flexDlg::OnNotEnoughThreadEventHandle_cb(ThreadPool* pThreadPool, void* user)
{
	if (pThreadPool->GetALLThreadsNumber()>=30)
	{
		LOG_DEBUG(glogger, MultUtf82Mult2("线程数已达上限：") << 30);
	} 
	else
	{
		int thNum = pThreadPool->AddThreads(1);
		LOG_DEBUG(glogger, MultUtf82Mult2("线程增加1个,总线程数：") << thNum);
	}
}

QString flexDlg::GetImgInfo_cb(sptr<HObject> Image, sptr<HObject> inRegion, sptr<HObject> OutRegion, sptr<HObject> OutXld, HTuple strType, HTuple HandleID)
{
	QString Type = strType.S().ToLocal8bit();
	QString text;
	if (Type == "放料标准位置") {
		HTuple findRow, findColumn, findAngle, iResult;
		HTuple Mat, Para;

		m_hdev->GetStdImgPoint(*Image, *inRegion, *OutRegion, *OutXld, 0, HandleID, Mat, Para, &findRow, &findColumn, &findAngle, &iResult);

		if (findRow.Length() == 0)
		{
			text = "获取模板坐标错误！\n";
		}
		else
		{
			text = "模板坐标X：" + QString::number(findRow.D(), 'f', 3) + "\n";
			text += "模板坐标Y：" + QString::number(findColumn.D(), 'f', 3) + "\n";
			text += "模板角度R：" + QString::number(findAngle.D(), 'f', 3) + "\n";
			m_pThis->m_stdX = findRow.D();
			m_pThis->m_stdY = findColumn.D();
			m_pThis->m_stdR = findAngle.D();
		}
	}
	return text;
}

int flexDlg::WriteRotateCenter2DB_cb(QString location, int number, double* CenterX, double* CenterY, double* offsetX, double* offsetY, double* offsetR, void* pBackup)
{
	if (location != "下相机") return -1;
	if (number > 6) {
		MessageBoxTip("超出下相机旋转中心数量！");
		return -1;
	}
	QString strTip = "是否更改" + location + QString::number(number) + "号吸嘴的旋转中心？";
	auto res = QMessageBox::StandardButton::NoButton;
	res = QMessageBox::information(0, "提示", strTip, QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::No);
	if(res== QMessageBox::StandardButton::No)return -1;
	GetmtfInstance()->UpdateValuesRow("conn1", "旋转中心",
	"X坐标=" + QString::number(*CenterX) + "," + "Y坐标=" + QString::number(*CenterY), "rowid="+QString::number(number +6));
	m_pThis->UpdataTable_RotateCenter();
	return 0;
}

int flexDlg::WriteStdPos2DB_cb(QString* location, int* number, double* X, double* Y, double* R, void* pCtrl, void* pBackup)
{
	if (*location == "放料标准位置") {
		if (*number > 24) {
			MessageBoxTip("超出标准位置数量！");
			return -1;
		}
		QString strTip = "是否更改"+ QString::number(*number) + "号" + *location+"图像坐标?";
		auto res = QMessageBox::StandardButton::NoButton;
		res = QMessageBox::information(0, "提示", strTip, QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::No);
		if (res == QMessageBox::StandardButton::No)return -1;
		GetmtfInstance()->UpdateValuesRow("conn1", "放料标准图像位置",
			"图像坐标X=" + QString::number(m_pThis->m_stdX) + "," + "图像坐标Y=" + QString::number(m_pThis->m_stdY) + "," + "角度R=" + QString::number(m_pThis->m_stdR),
			"rowid=" + QString::number(*number));
		m_pThis->UpdataTable_StandImgPos();
	}
	return 0;
}

void flexDlg::DispWorkRateInfo_cb(QTabWidget* tabWidget)
{
	m_pflexdb = mksptr<flexdb>();
	m_pWorkRateDlg = new QWorkRateDlg();
	tabWidget->addTab(m_pWorkRateDlg, "设备状态信息");
}

void flexDlg::timerEvent(QTimerEvent* event)
{
	if ((event->timerId() == m_TimerId_heart) && m_pflexComm->m_bCheckHeartBeat)
	{
		m_pflexComm->HeartBeat();
	}
}

void flexDlg::Write2DCodeCsvHeader(QString filePath)
{
	std::ofstream outFile;
	outFile.open(filePath.tostr(), ios::out | ios::app);
	outFile << QString("扫码时间").tostr() << ',' << QString("吸嘴编号").tostr() << ',' << QString("二维码").tostr() << ',' << QString("MES校验").tostr() << ',' << endl;
	outFile.close();
	CleanUpRubbishDocuments();
}

void flexDlg::WriteRepeatTestCsvHeader(QString filePath)
{
	std::ofstream outFile;
	outFile.open(filePath.tostr(), ios::out | ios::app);
	outFile << QString("测试时间").tostr() << ',' 
		    << QString("吸嘴编号").tostr() << ','
		    << QString("图像坐标X").tostr() << ',' 
		    << QString("图像坐标Y").tostr() << ',' 
		    << QString("图像角度R").tostr() << ','
		    << QString("实际补偿X").tostr() << ','
		    << QString("实际补偿Y").tostr() << ','
		    << QString("实际补偿R").tostr() << ','
		    << endl;
	outFile.close();
}

void flexDlg::Write2DCodeCsvData(QString time, int NozzleIndex, QString sn, QString mesResult, QString filePath)
{
	std::ofstream outFile;
	outFile.open(filePath.tostr(), ios::out | ios::app);
	outFile << time.tostr() << ',' << NozzleIndex << ',' << sn.tostr() << ',' << mesResult.tostr() << ',' << endl;
	outFile.close();
}

void flexDlg::WriteRepeatTestCsvData(QString time, int NozzleIndex, double imgX, double imgY, double imgR, double offsetX, double offsetY, double offsetR, QString filePath)
{
	std::ofstream outFile;
	outFile.open(filePath.tostr(), ios::out | ios::app);
	//QString time = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
	outFile << time.tostr() << ','
		    << NozzleIndex << ','
		    << imgX << ','
		    << imgY << ','
		    << imgR << ','
		    << offsetX << ','
		    << offsetY << ','
		    << offsetR << ','
		    << endl;
	outFile.close();
}

int flexDlg::ReadCheckSnCsvData(QString filePath, std::map<QString,int>& SnDataMap)
{
	std::ifstream inFile(filePath.tostr(), std::ios::in);
	if (!inFile.is_open())
	{
		MessageBoxTip("点检数据加载失败！");
		return -2;
	}
	std::string lineStr;

	while (std::getline(inFile, lineStr))
	{
		std::stringstream ssline(lineStr);
		std::string str;
		for (int col = 0; std::getline(ssline, str, ';'); col++)
		{
			SnDataMap[toqstr(str)]= col;
		}
	}
	inFile.close();
	return 0;
}

void flexDlg::WritePutDutDataCsvHeader(QString filePath)
{
	std::ofstream outFile;
	outFile.open(filePath.tostr(), ios::out | ios::app);
	outFile << QString("测试时间").tostr() << ','
		<< QString("二维码").tostr() << ','
		<< QString("吸嘴编号").tostr() << ','
		<< QString("图像坐标X").tostr() << ','
		<< QString("图像坐标Y").tostr() << ','
		<< QString("图像角度R").tostr() << ','
		<< QString("实际补偿X").tostr() << ','
		<< QString("实际补偿Y").tostr() << ','
		<< QString("实际补偿R").tostr() << ','
		<< endl;
	outFile.close();
}

void flexDlg::WritePutDutDataCsvData(QString time, int NozzleIndex, QString sn, double imgX, double imgY, double imgR, double offsetX, double offsetY, double offsetR, QString filePath)
{
	std::ofstream outFile;
	outFile.open(filePath.tostr(), ios::out | ios::app);
	outFile << time.tostr() << ','
		<< sn.tostr() << ','
		<< NozzleIndex << ','
		<< imgX << ','
		<< imgY << ','
		<< imgR << ','
		<< offsetX << ','
		<< offsetY << ','
		<< offsetR << ','
		<< endl;
	outFile.close();
}

void flexDlg::WritePLCWarningCsvHeader(QString filePath)
{
	std::ofstream outFile;
	outFile.open(filePath.tostr(), ios::out | ios::app);
	outFile << QString("报警时间").tostr() << ',' << QString("报警编号").tostr() << ',' << QString("报警内容").tostr() << ',' << endl;
	outFile.close();
}

void flexDlg::WritePLCWarningCsvData(QString time, int WarningNo, QString Content, QString filePath)
{
	std::ofstream outFile;
	outFile.open(filePath.tostr(), ios::out | ios::app);
	outFile << time.tostr() << ','<< WarningNo << ',' << Content.tostr() << ',' << endl;
	outFile.close();
}

void flexDlg::WriteWorkRateCsvHeader()
{
	QDateTime DataTime = QDateTime::currentDateTime();
	QString strData = DataTime.date().toString("yyyy-MM-dd");
	QString filePath = m_WorkRateFolderPath + "/" + GetSetTableName() + ".csv";
	if (GetmtfInstance()->isFileExist(filePath)) return;

	std::ofstream outFile;
	outFile.open(filePath.tostr(), ios::out | ios::app);
	outFile << QString("时间").tostr() << ',' 
		<< QString("总时长").tostr() << ','

		<< QString("生产时间/H").tostr() << ','
		<< QString("待料时间/H").tostr() << ','
		<< QString("报警时间/H").tostr() << ','
		<< QString("故障时间/H").tostr() << ','
		<< QString("产量/H").tostr() << ','

		<< QString("稼动率/H").tostr() << ','
		<< QString("待料率/H").tostr() << ','
		<< QString("故障率/H").tostr() << ','

		<< QString("总生产时间").tostr() << ','
		<< QString("总待料时间").tostr() << ','
		<< QString("总报警时间").tostr() << ','
		<< QString("总故障时间").tostr() << ','
		<< QString("总产量").tostr() << ','

		<< QString("总稼动率").tostr() << ','
		<< QString("总待机率").tostr() << ','
		<< QString("总故障率").tostr() << ','

		<< QString("定位失败/H").tostr() << ','
		<< QString("总定位失败").tostr() << ','

		<< endl;
	outFile.close();
}

void flexDlg::WriteWorkRateCsvData(INT64 totalTime,
	INT64 workTime, INT64 waitTime, INT64 WarningTime, INT64 faultTime, int outPut,
	double workRate, double waitRate, double faultRate,
	INT64 totalWorkTime, INT64 totalWaitTime, INT64 totalWarningTime, INT64 totalFaultTime, int totalOutPut,
	double totalWorkRate, double totalWaitRate, double totalFaultRate,
	int curPositingFail, int  TotalPositingFail
	)
{
	QDateTime DataTime = QDateTime::currentDateTime();
	QString strData = DataTime.date().toString("yyyy-MM-dd");
	QString strTimeDot = DataTime.time().toString("hh:mm:ss");

	QString filePath = m_WorkRateFolderPath + "/" + GetSetTableName() + ".csv";
	if (!GetmtfInstance()->isFileExist(filePath))
	{
		WriteWorkRateCsvHeader();
	}
	std::ofstream outFile;
	outFile.open(filePath.tostr(), ios::out | ios::app);
	outFile << strTimeDot.tostr() << ','  << totalTime << ','
		    << workTime << ',' << waitTime << ',' << WarningTime << ',' << faultTime << ','<< outPut<<","
		    << Round_off(workRate, 3) << ',' << Round_off(waitRate, 3) << ',' << Round_off(faultRate, 3) << ','
		    << totalWorkTime << ',' << totalWaitTime << ',' << totalWarningTime << ',' << totalFaultTime << ',' << totalOutPut << ","
		    << Round_off(totalWorkRate, 3) << ',' << Round_off(totalWaitRate, 3) << ',' << Round_off(totalFaultRate, 3) << ','
		    << curPositingFail << ',' << TotalPositingFail << ","
		    << endl;
	outFile.close();
}

void flexDlg::ClearFlexData(QString Path, int days)
{
	QFileInfoList dirinfo = GetmtfInstance()->ReadAllFileInfoFromDir(Path, "*");
	for (auto e : dirinfo)
	{
		if (e.fileName() != "." && e.fileName() != "..")
		{
			int day, hour, minute, second;
			QDateTime datatime = e.birthTime();
			GetmtfInstance()->CurrentTimeToPast(datatime, day, hour, minute, second);
			if (day > days)
			{
				if (e.isDir())
				{
					GetmtfInstance()->deleteDir(e.absoluteFilePath());
				}
				else
				{
					e.dir().remove(e.absoluteFilePath());
				}
			}
		}
	}
	return;
}

void flexDlg::CleanUpRubbishDocuments()
{
	auto fun = [=] {
		ClearFlexData(m_RectificationDataFolderPath, m_Days);
		ClearFlexData(m_FlexPictureFolderPath, m_Days);
		ClearFlexData(m_RepeatTestDataFolderPath, m_Days);
		ClearFlexData(m_SaveSnMesCheckCsvFolderPath, m_Days);
		ClearFlexData(m_PlcLogDataFolderPath, m_Days);
		ClearFlexData(Icg::getAppConfigInfo().SaveDetectFailPicPath + "/Camera_0", m_Days);
		ClearFlexData(Icg::getAppConfigInfo().SaveDetectFailPicPath+"/Camera_1", m_Days);
		ClearFlexData(m_WorkRateFolderPath, m_Days);
	};
	gthpool->AddTask(fun);
}

void flexDlg::ReadWarningInfo()
{
	QString filePath = GetmtfInstance()->CreateInnerFile(0, "", "flex/File/WarningInfo/报警信息.csv");
	std::ifstream inFile(filePath.tostr(), std::ios::in);
	if (!inFile.is_open())
	{
		//log("报警数据加载失败！");
		LOG_DEBUG(glogger, MultUtf82Mult2("报警数据加载失败！"));
		return;
	}
	std::string lineStr;
	while (getline(inFile, lineStr))
	{
		if (lineStr.empty())
		{
			continue;
		}
		std::stringstream ssline(lineStr);
		std::string str;
		int warningNum = -1;
		while (getline(ssline, str, ','))
		{
			if (isDigitStr(toqstr(str)))
			{
				warningNum = toqstr(str).toInt();
			}
			else
			{
				m_WarningMap[warningNum] = toqstr(str);
			}
		}
	}
	inFile.close();
	return;
}

void flexDlg::InitLight()
{
	try
	{
		for (auto i = 0; i < m_LightIntensity.size() - 2 && Icg::getControlNum() != 0; i++)
		{
			if (Icg::getNameControlMap()[CTRL_NAME_0] != nullptr)	Icg::getNameControlMap()[CTRL_NAME_0]->SetIntensity(m_vecLightChannel.at(i), m_LightIntensity.at(i).P0);
			if ((Icg::getNameControlMap()[CTRL_NAME_0] != nullptr) && (i < 2 || !m_bAlwaysBright))	Icg::getNameControlMap()[CTRL_NAME_0]->CloseChannel(m_vecLightChannel.at(i));
		}
	}
	catch (...)
	{
		MessageBoxTip("打开光源控制器出错！");
	}
}

void flexDlg::InitCameraPara()
{
	if (Icg::getNameCameraMap()[CAM_NAME_0] != nullptr)
	{
		Icg::getNameCameraMap()[CAM_NAME_0]->SetExposure(m_CameraPara.at(0).P0);
		Icg::getNameCameraMap()[CAM_NAME_0]->SetGain(m_CameraPara.at(0).P1);
		Icg::getNameCameraMap()[CAM_NAME_0]->SetGamma(m_CameraPara.at(0).P2);
	}
	if (Icg::getNameCameraMap()[CAM_NAME_1] != nullptr)
	{
		Icg::getNameCameraMap()[CAM_NAME_1]->SetExposure(m_CameraPara.at(1).P0);
		Icg::getNameCameraMap()[CAM_NAME_1]->SetGain(m_CameraPara.at(1).P1);
		Icg::getNameCameraMap()[CAM_NAME_1]->SetGamma(m_CameraPara.at(1).P2);
	}
	if (Icg::getNameCameraMap()[CAM_NAME_2] != nullptr)
	{
		Icg::getNameCameraMap()[CAM_NAME_2]->SetExposure(m_CameraPara.at(2).P0);
		Icg::getNameCameraMap()[CAM_NAME_2]->SetGain(m_CameraPara.at(2).P1);
		Icg::getNameCameraMap()[CAM_NAME_2]->SetGamma(m_CameraPara.at(2).P2);
	}
}

void flexDlg::ConnectStateFun_cb(int CameraIndex, QString CameraStatus, void* pUser)
{
	if (CameraIndex==0)
	{
		LOG_TRACE(GetmtpLogger(), "Camera 0 "<< CameraStatus.toStdString());
	}
	else if (CameraIndex == 1)
	{
		LOG_TRACE(GetmtpLogger(), "Camera 1 " << CameraStatus.toStdString());
	}
}